summaryrefslogtreecommitdiffstats
path: root/private/ntos/ndis/ndiswan
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/ndis/ndiswan
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to 'private/ntos/ndis/ndiswan')
-rw-r--r--private/ntos/ndis/ndiswan/adapter.h132
-rw-r--r--private/ntos/ndis/ndiswan/ccp.c456
-rw-r--r--private/ntos/ndis/ndiswan/compress.c1689
-rw-r--r--private/ntos/ndis/ndiswan/compress.h187
-rw-r--r--private/ntos/ndis/ndiswan/dirs26
-rw-r--r--private/ntos/ndis/ndiswan/export/makefile6
-rw-r--r--private/ntos/ndis/ndiswan/export/sources59
-rw-r--r--private/ntos/ndis/ndiswan/global.h52
-rw-r--r--private/ntos/ndis/ndiswan/indicate.c611
-rw-r--r--private/ntos/ndis/ndiswan/io.c4608
-rw-r--r--private/ntos/ndis/ndiswan/kdexts/api.c385
-rw-r--r--private/ntos/ndis/ndiswan/kdexts/display.c543
-rw-r--r--private/ntos/ndis/ndiswan/kdexts/display.h54
-rw-r--r--private/ntos/ndis/ndiswan/kdexts/makefile6
-rw-r--r--private/ntos/ndis/ndiswan/kdexts/sources49
-rw-r--r--private/ntos/ndis/ndiswan/kdexts/wanhelp.c183
-rw-r--r--private/ntos/ndis/ndiswan/kdexts/wanhelp.def48
-rw-r--r--private/ntos/ndis/ndiswan/kdexts/wanhelp.h99
-rw-r--r--private/ntos/ndis/ndiswan/kdexts/wanhelp.rc12
-rw-r--r--private/ntos/ndis/ndiswan/loopback.c148
-rw-r--r--private/ntos/ndis/ndiswan/memory.c1624
-rw-r--r--private/ntos/ndis/ndiswan/miniport.c576
-rw-r--r--private/ntos/ndis/ndiswan/ndiswan.c1346
-rw-r--r--private/ntos/ndis/ndiswan/ndiswan.rc43
-rw-r--r--private/ntos/ndis/ndiswan/protocol.c723
-rw-r--r--private/ntos/ndis/ndiswan/receive.c2865
-rw-r--r--private/ntos/ndis/ndiswan/request.c541
-rw-r--r--private/ntos/ndis/ndiswan/send.c3080
-rw-r--r--private/ntos/ndis/ndiswan/tapi.c144
-rw-r--r--private/ntos/ndis/ndiswan/tcpip.h52
-rw-r--r--private/ntos/ndis/ndiswan/util.c323
-rw-r--r--private/ntos/ndis/ndiswan/vjslip.c885
-rw-r--r--private/ntos/ndis/ndiswan/vjslip.h249
-rw-r--r--private/ntos/ndis/ndiswan/wan.h42
-rw-r--r--private/ntos/ndis/ndiswan/wandefs.h649
-rw-r--r--private/ntos/ndis/ndiswan/wanproto.h696
-rw-r--r--private/ntos/ndis/ndiswan/wantypes.h505
37 files changed, 23696 insertions, 0 deletions
diff --git a/private/ntos/ndis/ndiswan/adapter.h b/private/ntos/ndis/ndiswan/adapter.h
new file mode 100644
index 000000000..17d0cc1ab
--- /dev/null
+++ b/private/ntos/ndis/ndiswan/adapter.h
@@ -0,0 +1,132 @@
+/*++
+
+Copyright (c) 1990-1995 Microsoft Corporation
+
+Module Name:
+
+ Adapter.h
+
+Abstract:
+
+ This file contains major data structures used by the NdisWan driver
+
+Author:
+
+ Tony Bell (TonyBe) June 06, 1995
+
+Environment:
+
+ Kernel Mode
+
+Revision History:
+
+ TonyBe 06/06/95 Created
+
+--*/
+
+#ifndef _NDISWAN_ADAPTER_
+#define _NDISWAN_ADAPTER_
+
+//
+// This is the control block for the NdisWan adapter that is created by the NDIS Wrapper
+// making a call to NdisWanInitialize. There should only be one call to initialize and
+// therefore only one adapter created.
+//
+typedef struct _ADAPTERCB {
+ LIST_ENTRY Linkage; // Used to link adapter into global list
+ ULONG ulAllocationSize; // Size of memory allocated
+ NDIS_SPIN_LOCK Lock; // Structure access lock
+ ULONG ulReferenceCount; // Adapter reference count
+ NDIS_HANDLE hMiniportHandle; // Assigned in MiniportInitialize
+#define RESET_IN_PROGRESS 0x00000001
+#define ASK_FOR_RESET 0x00000002
+#define MINIPORT_LOCK_OWNER 0x00000004
+
+#ifdef USE_NDIS_MINIPORT_CALLBACK
+#define DEFERRED_CALLBACK_SET 0x00000008
+#else // end of USE_NDIS_MINIPORT_CALLBACK
+#define DEFERRED_TIMER_SET 0x00000008
+#endif // end of !USE_NDIS_MINIPORT_CALLBACK
+
+#define RECEIVE_COMPLETE 0x00000010
+ ULONG Flags;
+
+#ifdef USE_NDIS_MINIPORT_LOCKING
+ NDIS_HANDLE SwitchHandle;
+#else // end of USE_NDIS_MINIPORT_LOCKING
+ WAN_IRQL MiniportLockIrql;
+ WAN_IRQL SavedIrql;
+#endif // end of !USE_NDIS_MINIPORT_LOCKING
+
+ DEFERRED_QUEUE FreeDeferredQueue;
+ DEFERRED_QUEUE DeferredQueue[MAX_DEFERRED_QUEUE_TYPES];
+
+#ifndef USE_NDIS_MINIPORT_CALLBACK
+ NDIS_MINIPORT_TIMER DeferredTimer;
+#endif // end of !USE_NDIS_MINIPORT_CALLBACK
+
+ NDIS_MEDIUM MediumType; // Medium type that we are emulating
+ NDIS_HARDWARE_STATUS HardwareStatus; // Hardware status (????)
+ NDIS_STRING AdapterName; // Adapter Name (????)
+ UCHAR NetworkAddress[ETH_LENGTH_OF_ADDRESS]; // Ethernet address for this adapter
+ ULONG ulNumberofProtocols;
+ USHORT ProtocolType;
+ struct _BUNDLECB *NbfBundleCB;
+ NDIS_HANDLE NbfProtocolHandle;
+#if DBG
+ LIST_ENTRY DbgNdisPacketList;
+#endif
+} ADAPTERCB, *PADAPTERCB;
+
+//
+// This is the control block for each WAN Miniport adapter that NdisWan binds to through
+// the NDIS Wrapper as a "protocol".
+//
+typedef struct _WAN_ADAPTERCB {
+ LIST_ENTRY Linkage; // Used to link adapter into global list
+ ULONG ulAllocationSize; // Size of memory allocated
+ NDIS_SPIN_LOCK Lock; // Structure access lock
+ LIST_ENTRY FreeLinkCBList; // Free pool of link control blocks for this WAN Miniport
+ NDIS_HANDLE hNdisBindingHandle; // Binding handle
+ NDIS_STRING MiniportName; // WAN Miniport name
+ NDIS_MEDIUM MediumType; // WAN Miniport medium type
+ NDIS_WAN_MEDIUM_SUBTYPE MediumSubType; // WAN Miniport medium subtype
+ NDIS_WAN_HEADER_FORMAT WanHeaderFormat; // WAN Miniport header type
+ WAN_EVENT NotificationEvent; // Async notification event for adapter operations (open, close, ...)
+ NDIS_STATUS NotificationStatus; // Notification status for async adapter events
+ PWAN_REQUEST pWanRequest; // 1st entry on WanRequest queue
+ PWAN_REQUEST pLastWanRequest; // Last entry on WanRequest queue
+ NDIS_WAN_INFO WanInfo; // WanInfo structure
+#if DBG
+ LIST_ENTRY DbgWanPacketList;
+#endif
+} WAN_ADAPTERCB, *PWAN_ADAPTERCB;
+
+//
+// Main control block for all global data
+//
+typedef struct _NDISWANCB {
+ NDIS_SPIN_LOCK Lock; // Structure access lock
+ NDIS_HANDLE hNdisWrapperHandle; // NDIS Wrapper handle
+ NDIS_HANDLE hProtocolHandle; // Our protocol handle
+ ULONG ulNumberOfProtocols; // Total number of protocols that we are bound to
+ ULONG ulNumberOfLinks; // Total number of links for all WAN Miniport Adapters
+ ULONG ulMinFragmentSize; // Minimum fragment size
+ ULONG ulTraceLevel; // Trace Level values 0 - 10 (10 verbose)
+ ULONG ulTraceMask; // Trace bit mask
+ PVOID pDriverObject; // Pointer to the NT Driver Object
+ PVOID pDeviceObject; // Pointer to the device object
+ ULONG SendCount;
+ ULONG SendCompleteCount;
+ ULONG IORecvError1;
+ ULONG IORecvError2;
+ PADAPTERCB PromiscuousAdapter;
+ NDIS_MINIPORT_TIMER RecvFlushTimer;
+
+#ifdef NT
+ PDRIVER_DISPATCH MajorFunction[IRP_MJ_MAXIMUM_FUNCTION+1]; // Device dispatch functions
+#endif
+
+}NDISWANCB, *PNDISWANCB;
+
+#endif // _NDISWAN_ADAPTER_
diff --git a/private/ntos/ndis/ndiswan/ccp.c b/private/ntos/ndis/ndiswan/ccp.c
new file mode 100644
index 000000000..645e01884
--- /dev/null
+++ b/private/ntos/ndis/ndiswan/ccp.c
@@ -0,0 +1,456 @@
+/*++
+
+Copyright (c) 1994 Microsoft Corporation
+
+Module Name:
+
+ ccp.c
+
+Abstract:
+
+
+Author:
+
+ Thomas J. Dimitri (TommyD) 29-March-1994
+
+Environment:
+
+Revision History:
+
+
+--*/
+
+#include "wan.h"
+
+#include <rc4.h>
+#include "compress.h"
+#include "tcpip.h"
+#include "vjslip.h"
+
+//
+// Assumes the endpoint lock is held
+//
+VOID
+WanDeallocateCCP(
+ PBUNDLECB BundleCB
+ )
+{
+ ULONG CompressSend;
+ ULONG CompressRecv;
+
+ NdisWanDbgOut(DBG_TRACE, DBG_CCP, ("WanDeallocateCCP: Enter"));
+
+ //
+ // Deallocate encryption keys.
+ //
+ if (BundleCB->SendRC4Key) {
+ NdisWanFreeMemory(BundleCB->SendRC4Key);
+
+ //
+ // Clear so we know it is deallocated
+ //
+ BundleCB->SendRC4Key= NULL;
+ }
+ if (BundleCB->SendEncryptInfo.Context) {
+ NdisWanFreeMemory(BundleCB->SendEncryptInfo.Context);
+
+ BundleCB->SendEncryptInfo.Context = NULL;
+ }
+
+ if (BundleCB->RecvRC4Key) {
+ NdisWanFreeMemory(BundleCB->RecvRC4Key);
+
+ //
+ // Clear it so we know it is deallocated
+ //
+ BundleCB->RecvRC4Key= NULL;
+ }
+ if (BundleCB->RecvEncryptInfo.Context) {
+ NdisWanFreeMemory(BundleCB->RecvEncryptInfo.Context);
+
+ BundleCB->RecvEncryptInfo.Context = NULL;
+ }
+
+
+ //
+ // Get compression context sizes
+ //
+ getcontextsizes (&CompressSend, &CompressRecv);
+
+ //
+ // Deallocate compression send/recv buffers
+ //
+ if (BundleCB->SendCompressContext) {
+ NdisWanFreeMemory(BundleCB->SendCompressContext);
+
+ BundleCB->SendCompressContext= NULL;
+ }
+
+ if (BundleCB->RecvCompressContext) {
+ NdisWanFreeMemory(BundleCB->RecvCompressContext);
+
+ BundleCB->RecvCompressContext= NULL;
+ }
+
+ //
+ // Any VJ header compression
+ //
+ if (BundleCB->VJCompress) {
+ NdisWanFreeMemory(BundleCB->VJCompress);
+
+ BundleCB->VJCompress = NULL;
+ }
+
+ //
+ // Turn off any compression/encryption
+ //
+ BundleCB->SendCompInfo.MSCompType =
+ BundleCB->RecvCompInfo.MSCompType = 0;
+
+ NdisWanDbgOut(DBG_TRACE, DBG_CCP, ("WanDeallocateCCP: Exit"));
+}
+
+
+//
+// Assumes the endpoint lock is held
+//
+NTSTATUS
+WanAllocateCCP(
+ PBUNDLECB BundleCB
+ )
+{
+ ULONG CompressSend;
+ ULONG CompressRecv;
+
+ NdisWanDbgOut(DBG_TRACE, DBG_CCP, ("WanAllocateCCP: Enter"));
+
+ //
+ // Reset all counters regardless
+ //
+ BundleCB->SCoherencyCounter =
+ BundleCB->RCoherencyCounter =
+ BundleCB->LastRC4Reset=
+ BundleCB->CCPIdentifier = 0;
+
+ //
+ // Is encryption enabled?
+ //
+#ifdef ENCRYPT_128BIT
+ if ((BundleCB->SendCompInfo.MSCompType &
+ (NDISWAN_ENCRYPTION | NDISWAN_40_ENCRYPTION | NDISWAN_128_ENCRYPTION))) {
+#else
+ if ((BundleCB->SendCompInfo.MSCompType &
+ (NDISWAN_ENCRYPTION | NDISWAN_40_ENCRYPTION))) {
+#endif
+
+ if (BundleCB->SendRC4Key == NULL) {
+ NdisWanAllocateMemory(&BundleCB->SendRC4Key, sizeof(struct RC4_KEYSTRUCT));
+
+ //
+ // If we can't allocate memory the machine is toast.
+ // Forget about freeing anything up.
+ //
+
+ if (BundleCB->SendRC4Key == NULL) {
+ NdisWanDbgOut(DBG_FAILURE, DBG_CCP, ("Can't allocate encryption key!"));
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+ }
+
+ if (BundleCB->SendCompInfo.MSCompType & NDISWAN_ENCRYPTION) {
+
+ //
+ // For legacy encryption we use the 8 byte LMSessionKey
+ // for initiali encryption session key. The first 256
+ // packets will be sent using this without any salt
+ // (the first 256 packets are using 64 bit encryption).
+ // After the first 256 we will always salt the first 3
+ // bytes of the encryption key so that we are doing 40
+ // bit encryption.
+ //
+ BundleCB->SendEncryptInfo.SessionKeyLength = MAX_SESSIONKEY_SIZE;
+
+ NdisMoveMemory(BundleCB->SendEncryptInfo.StartKey,
+ BundleCB->SendCompInfo.LMSessionKey,
+ BundleCB->SendEncryptInfo.SessionKeyLength);
+
+ NdisMoveMemory(BundleCB->SendEncryptInfo.SessionKey,
+ BundleCB->SendEncryptInfo.StartKey,
+ BundleCB->SendEncryptInfo.SessionKeyLength);
+
+#if DBG
+ DbgPrint("NDISWAN: Send using legacy 40 bit encryption\n");
+#endif
+
+ } else if (BundleCB->SendCompInfo.MSCompType & NDISWAN_40_ENCRYPTION) {
+
+ if (NDIS_STATUS_SUCCESS != InitSHAContext(&BundleCB->SendEncryptInfo)) {
+ NdisWanDbgOut(DBG_FAILURE, DBG_CCP, ("Can't allocate sha encryption key!"));
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ //
+ // For our new 40 bit encryption we will use SHA on the
+ // 8 byte LMSessionKey to derive our intial 8 byte
+ // encryption session key. We will always salt the first
+ // 3 bytes so that we are doing 40 bit encryption.
+ //
+ BundleCB->SendEncryptInfo.SessionKeyLength = MAX_SESSIONKEY_SIZE;
+
+ NdisMoveMemory(BundleCB->SendEncryptInfo.StartKey,
+ BundleCB->SendCompInfo.LMSessionKey,
+ BundleCB->SendEncryptInfo.SessionKeyLength);
+
+ NdisMoveMemory(BundleCB->SendEncryptInfo.SessionKey,
+ BundleCB->SendEncryptInfo.StartKey,
+ BundleCB->SendEncryptInfo.SessionKeyLength);
+
+ GetNewKeyFromSHA(&BundleCB->SendEncryptInfo);
+
+ //
+ // Salt the first 3 bytes
+ //
+ BundleCB->SendEncryptInfo.SessionKey[0] = 0xD1;
+ BundleCB->SendEncryptInfo.SessionKey[1] = 0x26;
+ BundleCB->SendEncryptInfo.SessionKey[2] = 0x9E;
+
+#if DBG
+ DbgPrint("NDISWAN: Send using new 40 bit encryption\n");
+#endif
+ }
+
+#ifdef ENCRYPT_128BIT
+ else if (BundleCB->SendCompInfo.MSCompType & NDISWAN_128_ENCRYPTION) {
+
+ if (NDIS_STATUS_SUCCESS != InitSHAContext(&BundleCB->SendEncryptInfo)) {
+ NdisWanDbgOut(DBG_FAILURE, DBG_CCP, ("Can't allocate sha encryption key!"));
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ //
+ // For our new 128 bit encryption we will use SHA on the
+ // 16 byte NTUserSessionKey and the 8 byte Challenge to
+ // derive our the intial 128 bit encryption session key.
+ //
+ BundleCB->SendEncryptInfo.SessionKeyLength = MAX_USERSESSIONKEY_SIZE;
+ NdisMoveMemory(BundleCB->SendEncryptInfo.StartKey,
+ BundleCB->SendCompInfo.UserSessionKey,
+ BundleCB->SendEncryptInfo.SessionKeyLength);
+
+
+ GetStartKeyFromSHA(&BundleCB->SendEncryptInfo,
+ BundleCB->SendCompInfo.Challenge);
+
+ GetNewKeyFromSHA(&BundleCB->SendEncryptInfo);
+
+#if DBG
+ DbgPrint("NDISWAN: Send using 128 bit encryption\n");
+#endif
+ }
+#endif
+
+ //
+ // Initialize the rc4 send table
+ //
+ NdisWanDbgOut(DBG_TRACE, DBG_CCP,
+ ("RC4 encryption KeyLength %d", BundleCB->SendEncryptInfo.SessionKeyLength));
+ NdisWanDbgOut(DBG_TRACE, DBG_CCP,
+ ("RC4 encryption Key %.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x %.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x",
+ BundleCB->SendEncryptInfo.SessionKey[0],
+ BundleCB->SendEncryptInfo.SessionKey[1],
+ BundleCB->SendEncryptInfo.SessionKey[2],
+ BundleCB->SendEncryptInfo.SessionKey[3],
+ BundleCB->SendEncryptInfo.SessionKey[4],
+ BundleCB->SendEncryptInfo.SessionKey[5],
+ BundleCB->SendEncryptInfo.SessionKey[6],
+ BundleCB->SendEncryptInfo.SessionKey[7],
+ BundleCB->SendEncryptInfo.SessionKey[8],
+ BundleCB->SendEncryptInfo.SessionKey[9],
+ BundleCB->SendEncryptInfo.SessionKey[10],
+ BundleCB->SendEncryptInfo.SessionKey[11],
+ BundleCB->SendEncryptInfo.SessionKey[12],
+ BundleCB->SendEncryptInfo.SessionKey[13],
+ BundleCB->SendEncryptInfo.SessionKey[14],
+ BundleCB->SendEncryptInfo.SessionKey[15]));
+
+ rc4_key(
+ BundleCB->SendRC4Key,
+ BundleCB->SendEncryptInfo.SessionKeyLength,
+ BundleCB->SendEncryptInfo.SessionKey);
+ }
+
+
+#ifdef ENCRYPT_128BIT
+ if ((BundleCB->RecvCompInfo.MSCompType &
+ (NDISWAN_ENCRYPTION | NDISWAN_40_ENCRYPTION | NDISWAN_128_ENCRYPTION))) {
+#else
+ if ((BundleCB->RecvCompInfo.MSCompType &
+ (NDISWAN_ENCRYPTION | NDISWAN_40_ENCRYPTION))) {
+#endif
+
+ if (BundleCB->RecvRC4Key == NULL) {
+ NdisWanAllocateMemory(&BundleCB->RecvRC4Key, sizeof(struct RC4_KEYSTRUCT));
+
+ //
+ // If we can't allocate memory the machine is toast.
+ // Forget about freeing anything up.
+ //
+ if (BundleCB->RecvRC4Key == NULL) {
+ NdisWanDbgOut(DBG_FAILURE, DBG_CCP, ("Can't allocate encryption key!"));
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+ }
+
+ if (BundleCB->RecvCompInfo.MSCompType & NDISWAN_ENCRYPTION) {
+ BundleCB->RecvEncryptInfo.SessionKeyLength = MAX_SESSIONKEY_SIZE;
+
+ NdisMoveMemory(BundleCB->RecvEncryptInfo.StartKey,
+ BundleCB->RecvCompInfo.LMSessionKey,
+ BundleCB->RecvEncryptInfo.SessionKeyLength);
+
+ NdisMoveMemory(BundleCB->RecvEncryptInfo.SessionKey,
+ BundleCB->RecvEncryptInfo.StartKey,
+ BundleCB->RecvEncryptInfo.SessionKeyLength);
+
+#if DBG
+ DbgPrint("NDISWAN: Recv using legacy 40 bit encryption\n");
+#endif
+ } else if (BundleCB->RecvCompInfo.MSCompType & (NDISWAN_40_ENCRYPTION)) {
+
+ if (NDIS_STATUS_SUCCESS != InitSHAContext(&BundleCB->RecvEncryptInfo)) {
+ NdisWanDbgOut(DBG_FAILURE, DBG_CCP, ("Can't allocate sha encryption key!"));
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ BundleCB->RecvEncryptInfo.SessionKeyLength = MAX_SESSIONKEY_SIZE;
+
+ NdisMoveMemory(BundleCB->RecvEncryptInfo.StartKey,
+ BundleCB->RecvCompInfo.LMSessionKey,
+ BundleCB->RecvEncryptInfo.SessionKeyLength);
+
+ NdisMoveMemory(BundleCB->RecvEncryptInfo.SessionKey,
+ BundleCB->RecvEncryptInfo.StartKey,
+ BundleCB->RecvEncryptInfo.SessionKeyLength);
+
+ GetNewKeyFromSHA(&BundleCB->RecvEncryptInfo);
+
+ //
+ // Salt the first 3 bytes
+ //
+ BundleCB->RecvEncryptInfo.SessionKey[0] = 0xD1;
+ BundleCB->RecvEncryptInfo.SessionKey[1] = 0x26;
+ BundleCB->RecvEncryptInfo.SessionKey[2] = 0x9E;
+
+#if DBG
+ DbgPrint("NDISWAN: Recv using new 40 bit encryption\n");
+#endif
+ }
+#ifdef ENCRYPT_128BIT
+ else if (BundleCB->RecvCompInfo.MSCompType & NDISWAN_128_ENCRYPTION) {
+
+ if (NDIS_STATUS_SUCCESS != InitSHAContext(&BundleCB->RecvEncryptInfo)) {
+ NdisWanDbgOut(DBG_FAILURE, DBG_CCP, ("Can't allocate sha encryption key!"));
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ BundleCB->RecvEncryptInfo.SessionKeyLength = MAX_USERSESSIONKEY_SIZE;
+ NdisMoveMemory(BundleCB->RecvEncryptInfo.StartKey,
+ BundleCB->RecvCompInfo.UserSessionKey,
+ BundleCB->RecvEncryptInfo.SessionKeyLength);
+
+ GetStartKeyFromSHA(&BundleCB->RecvEncryptInfo,
+ BundleCB->RecvCompInfo.Challenge);
+
+ GetNewKeyFromSHA(&BundleCB->RecvEncryptInfo);
+
+#if DBG
+ DbgPrint("NDISWAN: Recv using 128 bit encryption\n");
+#endif
+ }
+#endif
+
+ //
+ // Initialize the rc4 receive table
+ //
+ NdisWanDbgOut(DBG_TRACE, DBG_CCP,
+ ("RC4 encryption KeyLength %d", BundleCB->RecvEncryptInfo.SessionKeyLength));
+ NdisWanDbgOut(DBG_TRACE, DBG_CCP,
+ ("RC4 encryption Key %.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x",
+ BundleCB->RecvEncryptInfo.SessionKey[0],
+ BundleCB->RecvEncryptInfo.SessionKey[1],
+ BundleCB->RecvEncryptInfo.SessionKey[2],
+ BundleCB->RecvEncryptInfo.SessionKey[3],
+ BundleCB->RecvEncryptInfo.SessionKey[4],
+ BundleCB->RecvEncryptInfo.SessionKey[5],
+ BundleCB->RecvEncryptInfo.SessionKey[6],
+ BundleCB->RecvEncryptInfo.SessionKey[7],
+ BundleCB->RecvEncryptInfo.SessionKey[8],
+ BundleCB->RecvEncryptInfo.SessionKey[9],
+ BundleCB->RecvEncryptInfo.SessionKey[10],
+ BundleCB->RecvEncryptInfo.SessionKey[11],
+ BundleCB->RecvEncryptInfo.SessionKey[12],
+ BundleCB->RecvEncryptInfo.SessionKey[13],
+ BundleCB->RecvEncryptInfo.SessionKey[14],
+ BundleCB->RecvEncryptInfo.SessionKey[15]));
+
+ rc4_key(
+ BundleCB->RecvRC4Key,
+ BundleCB->RecvEncryptInfo.SessionKeyLength,
+ BundleCB->RecvEncryptInfo.SessionKey);
+ }
+
+ //
+ // Get compression context sizes
+ //
+ getcontextsizes (&CompressSend, &CompressRecv);
+
+ if (BundleCB->SendCompInfo.MSCompType & NDISWAN_COMPRESSION) {
+
+ if (BundleCB->SendCompressContext == NULL) {
+ NdisWanAllocateMemory(&BundleCB->SendCompressContext, CompressSend);
+ //
+ // If we can't allocate memory the machine is toast.
+ // Forget about freeing anything up.
+ //
+ if (BundleCB->SendCompressContext == NULL) {
+ NdisWanDbgOut(DBG_FAILURE, DBG_CCP, ("Can't allocate compression!"));
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+
+ }
+
+ //
+ // Initialize the compression history table and tree
+ //
+ initsendcontext (BundleCB->SendCompressContext);
+ }
+
+ if (BundleCB->RecvCompInfo.MSCompType & NDISWAN_COMPRESSION) {
+
+ if (BundleCB->RecvCompressContext == NULL) {
+ NdisWanAllocateMemory(&BundleCB->RecvCompressContext, CompressRecv);
+
+ //
+ // If we can't allocate memory the machine is toast.
+ // Forget about freeing anything up.
+ //
+ if (BundleCB->RecvCompressContext == NULL) {
+ NdisWanDbgOut(DBG_FAILURE, DBG_CCP, ("Can't allocate decompression"));
+ return(STATUS_INSUFFICIENT_RESOURCES);
+ }
+ }
+
+ //
+ // Initialize the decompression history table
+ //
+ initrecvcontext (BundleCB->RecvCompressContext);
+ }
+
+ //
+ // Next packet out is flushed
+ //
+ BundleCB->Flags |= RECV_PACKET_FLUSH;
+
+ NdisWanDbgOut(DBG_TRACE, DBG_CCP, ("WanAllocateCCP: Exit"));
+ return(STATUS_SUCCESS);
+}
diff --git a/private/ntos/ndis/ndiswan/compress.c b/private/ntos/ndis/ndiswan/compress.c
new file mode 100644
index 000000000..141da0929
--- /dev/null
+++ b/private/ntos/ndis/ndiswan/compress.c
@@ -0,0 +1,1689 @@
+//************************************************************************
+// Microsoft Corporation
+// Copyright(c) Microsoft Corp., 1990-1992
+//
+//
+// Revision history:
+// 5/5/94 Created gurdeep
+//
+//************************************************************************
+
+//#define COMP_12K
+
+#include "wan.h"
+#include "compress.h"
+
+
+//#define DEBUG
+
+unsigned long lookup_array1[256] = {
+ 0, 10276755, 20553510, 30830265,
+ 41107020, 51383775, 61660530, 71937285,
+ 82214040, 92490795, 102767550, 113044305,
+ 123321060, 133597815, 143874570, 154151325,
+ 164428080, 174704835, 184981590, 195258345,
+ 205535100, 215811855, 226088610, 236365365,
+ 246642120, 256918875, 267195630, 277472385,
+ 287749140, 298025895, 308302650, 318579405,
+ 328856160, 339132915, 349409670, 359686425,
+ 369963180, 380239935, 390516690, 400793445,
+ 411070200, 421346955, 431623710, 441900465,
+ 452177220, 462453975, 472730730, 483007485,
+ 493284240, 503560995, 513837750, 524114505,
+ 534391260, 544668015, 554944770, 565221525,
+ 575498280, 585775035, 596051790, 606328545,
+ 616605300, 626882055, 637158810, 647435565,
+ 657712320, 667989075, 678265830, 688542585,
+ 698819340, 709096095, 719372850, 729649605,
+ 739926360, 750203115, 760479870, 770756625,
+ 781033380, 791310135, 801586890, 811863645,
+ 822140400, 832417155, 842693910, 852970665,
+ 863247420, 873524175, 883800930, 894077685,
+ 904354440, 914631195, 924907950, 935184705,
+ 945461460, 955738215, 966014970, 976291725,
+ 986568480, 996845235, 1007121990, 1017398745,
+ 1027675500, 1037952255, 1048229010, 1058505765,
+ 1068782520, 1079059275, 1089336030, 1099612785,
+ 1109889540, 1120166295, 1130443050, 1140719805,
+ 1150996560, 1161273315, 1171550070, 1181826825,
+ 1192103580, 1202380335, 1212657090, 1222933845,
+ 1233210600, 1243487355, 1253764110, 1264040865,
+ 1274317620, 1284594375, 1294871130, 1305147885,
+ 1315424640, 1325701395, 1335978150, 1346254905,
+ 1356531660, 1366808415, 1377085170, 1387361925,
+ 1397638680, 1407915435, 1418192190, 1428468945,
+ 1438745700, 1449022455, 1459299210, 1469575965,
+ 1479852720, 1490129475, 1500406230, 1510682985,
+ 1520959740, 1531236495, 1541513250, 1551790005,
+ 1562066760, 1572343515, 1582620270, 1592897025,
+ 1603173780, 1613450535, 1623727290, 1634004045,
+ 1644280800, 1654557555, 1664834310, 1675111065,
+ 1685387820, 1695664575, 1705941330, 1716218085,
+ 1726494840, 1736771595, 1747048350, 1757325105,
+ 1767601860, 1777878615, 1788155370, 1798432125,
+ 1808708880, 1818985635, 1829262390, 1839539145,
+ 1849815900, 1860092655, 1870369410, 1880646165,
+ 1890922920, 1901199675, 1911476430, 1921753185,
+ 1932029940, 1942306695, 1952583450, 1962860205,
+ 1973136960, 1983413715, 1993690470, 2003967225,
+ 2014243980, 2024520735, 2034797490, 2045074245,
+ 2055351000, 2065627755, 2075904510, 2086181265,
+ 2096458020, 2106734775, 2117011530, 2127288285,
+ 2137565040, 2147841795, 2158118550, 2168395305,
+ 2178672060, 2188948815, 2199225570, 2209502325,
+ 2219779080, 2230055835, 2240332590, 2250609345,
+ 2260886100, 2271162855, 2281439610, 2291716365,
+ 2301993120, 2312269875, 2322546630, 2332823385,
+ 2343100140, 2353376895, 2363653650, 2373930405,
+ 2384207160, 2394483915, 2404760670, 2415037425,
+ 2425314180, 2435590935, 2445867690, 2456144445,
+ 2466421200, 2476697955, 2486974710, 2497251465,
+ 2507528220, 2517804975, 2528081730, 2538358485,
+ 2548635240, 2558911995, 2569188750, 2579465505,
+ 2589742260, 2600019015, 2610295770, 2620572525
+};
+
+/*
+ for i = 0 to 255,
+ lookup_array2[i] = lookup_array1[i] << 8;
+*/
+unsigned long lookup_array2[256] = {
+ 0, 2630849280, 966731264, 3597580544,
+ 1933462528, 269344512, 2900193792, 1236075776,
+ 3866925056, 2202807040, 538689024, 3169538304,
+ 1505420288, 4136269568, 2472151552, 808033536,
+ 3438882816, 1774764800, 110646784, 2741496064,
+ 1077378048, 3708227328, 2044109312, 379991296,
+ 3010840576, 1346722560, 3977571840, 2313453824,
+ 649335808, 3280185088, 1616067072, 4246916352,
+ 2582798336, 918680320, 3549529600, 1885411584,
+ 221293568, 2852142848, 1188024832, 3818874112,
+ 2154756096, 490638080, 3121487360, 1457369344,
+ 4088218624, 2424100608, 759982592, 3390831872,
+ 1726713856, 62595840, 2693445120, 1029327104,
+ 3660176384, 1996058368, 331940352, 2962789632,
+ 1298671616, 3929520896, 2265402880, 601284864,
+ 3232134144, 1568016128, 4198865408, 2534747392,
+ 870629376, 3501478656, 1837360640, 173242624,
+ 2804091904, 1139973888, 3770823168, 2106705152,
+ 442587136, 3073436416, 1409318400, 4040167680,
+ 2376049664, 711931648, 3342780928, 1678662912,
+ 14544896, 2645394176, 981276160, 3612125440,
+ 1948007424, 283889408, 2914738688, 1250620672,
+ 3881469952, 2217351936, 553233920, 3184083200,
+ 1519965184, 4150814464, 2486696448, 822578432,
+ 3453427712, 1789309696, 125191680, 2756040960,
+ 1091922944, 3722772224, 2058654208, 394536192,
+ 3025385472, 1361267456, 3992116736, 2327998720,
+ 663880704, 3294729984, 1630611968, 4261461248,
+ 2597343232, 933225216, 3564074496, 1899956480,
+ 235838464, 2866687744, 1202569728, 3833419008,
+ 2169300992, 505182976, 3136032256, 1471914240,
+ 4102763520, 2438645504, 774527488, 3405376768,
+ 1741258752, 77140736, 2707990016, 1043872000,
+ 3674721280, 2010603264, 346485248, 2977334528,
+ 1313216512, 3944065792, 2279947776, 615829760,
+ 3246679040, 1582561024, 4213410304, 2549292288,
+ 885174272, 3516023552, 1851905536, 187787520,
+ 2818636800, 1154518784, 3785368064, 2121250048,
+ 457132032, 3087981312, 1423863296, 4054712576,
+ 2390594560, 726476544, 3357325824, 1693207808,
+ 29089792, 2659939072, 995821056, 3626670336,
+ 1962552320, 298434304, 2929283584, 1265165568,
+ 3896014848, 2231896832, 567778816, 3198628096,
+ 1534510080, 4165359360, 2501241344, 837123328,
+ 3467972608, 1803854592, 139736576, 2770585856,
+ 1106467840, 3737317120, 2073199104, 409081088,
+ 3039930368, 1375812352, 4006661632, 2342543616,
+ 678425600, 3309274880, 1645156864, 4276006144,
+ 2611888128, 947770112, 3578619392, 1914501376,
+ 250383360, 2881232640, 1217114624, 3847963904,
+ 2183845888, 519727872, 3150577152, 1486459136,
+ 4117308416, 2453190400, 789072384, 3419921664,
+ 1755803648, 91685632, 2722534912, 1058416896,
+ 3689266176, 2025148160, 361030144, 2991879424,
+ 1327761408, 3958610688, 2294492672, 630374656,
+ 3261223936, 1597105920, 4227955200, 2563837184,
+ 899719168, 3530568448, 1866450432, 202332416,
+ 2833181696, 1169063680, 3799912960, 2135794944,
+ 471676928, 3102526208, 1438408192, 4069257472,
+ 2405139456, 741021440, 3371870720, 1707752704,
+ 43634688, 2674483968, 1010365952, 3641215232,
+ 1977097216, 312979200, 2943828480, 1279710464,
+ 3910559744, 2246441728, 582323712, 3213172992,
+ 1549054976, 4179904256, 2515786240, 851668224
+};
+
+/*
+ for i = 0 to 255,
+ lookup_array3[i] = lookup_array1[i] << 16;
+*/
+unsigned long lookup_array3[256] = {
+ 0, 3482517504, 2670067712, 1857617920,
+ 1045168128, 232718336, 3715235840, 2902786048,
+ 2090336256, 1277886464, 465436672, 3947954176,
+ 3135504384, 2323054592, 1510604800, 698155008,
+ 4180672512, 3368222720, 2555772928, 1743323136,
+ 930873344, 118423552, 3600941056, 2788491264,
+ 1976041472, 1163591680, 351141888, 3833659392,
+ 3021209600, 2208759808, 1396310016, 583860224,
+ 4066377728, 3253927936, 2441478144, 1629028352,
+ 816578560, 4128768, 3486646272, 2674196480,
+ 1861746688, 1049296896, 236847104, 3719364608,
+ 2906914816, 2094465024, 1282015232, 469565440,
+ 3952082944, 3139633152, 2327183360, 1514733568,
+ 702283776, 4184801280, 3372351488, 2559901696,
+ 1747451904, 935002112, 122552320, 3605069824,
+ 2792620032, 1980170240, 1167720448, 355270656,
+ 3837788160, 3025338368, 2212888576, 1400438784,
+ 587988992, 4070506496, 3258056704, 2445606912,
+ 1633157120, 820707328, 8257536, 3490775040,
+ 2678325248, 1865875456, 1053425664, 240975872,
+ 3723493376, 2911043584, 2098593792, 1286144000,
+ 473694208, 3956211712, 3143761920, 2331312128,
+ 1518862336, 706412544, 4188930048, 3376480256,
+ 2564030464, 1751580672, 939130880, 126681088,
+ 3609198592, 2796748800, 1984299008, 1171849216,
+ 359399424, 3841916928, 3029467136, 2217017344,
+ 1404567552, 592117760, 4074635264, 3262185472,
+ 2449735680, 1637285888, 824836096, 12386304,
+ 3494903808, 2682454016, 1870004224, 1057554432,
+ 245104640, 3727622144, 2915172352, 2102722560,
+ 1290272768, 477822976, 3960340480, 3147890688,
+ 2335440896, 1522991104, 710541312, 4193058816,
+ 3380609024, 2568159232, 1755709440, 943259648,
+ 130809856, 3613327360, 2800877568, 1988427776,
+ 1175977984, 363528192, 3846045696, 3033595904,
+ 2221146112, 1408696320, 596246528, 4078764032,
+ 3266314240, 2453864448, 1641414656, 828964864,
+ 16515072, 3499032576, 2686582784, 1874132992,
+ 1061683200, 249233408, 3731750912, 2919301120,
+ 2106851328, 1294401536, 481951744, 3964469248,
+ 3152019456, 2339569664, 1527119872, 714670080,
+ 4197187584, 3384737792, 2572288000, 1759838208,
+ 947388416, 134938624, 3617456128, 2805006336,
+ 1992556544, 1180106752, 367656960, 3850174464,
+ 3037724672, 2225274880, 1412825088, 600375296,
+ 4082892800, 3270443008, 2457993216, 1645543424,
+ 833093632, 20643840, 3503161344, 2690711552,
+ 1878261760, 1065811968, 253362176, 3735879680,
+ 2923429888, 2110980096, 1298530304, 486080512,
+ 3968598016, 3156148224, 2343698432, 1531248640,
+ 718798848, 4201316352, 3388866560, 2576416768,
+ 1763966976, 951517184, 139067392, 3621584896,
+ 2809135104, 1996685312, 1184235520, 371785728,
+ 3854303232, 3041853440, 2229403648, 1416953856,
+ 604504064, 4087021568, 3274571776, 2462121984,
+ 1649672192, 837222400, 24772608, 3507290112,
+ 2694840320, 1882390528, 1069940736, 257490944,
+ 3740008448, 2927558656, 2115108864, 1302659072,
+ 490209280, 3972726784, 3160276992, 2347827200,
+ 1535377408, 722927616, 4205445120, 3392995328,
+ 2580545536, 1768095744, 955645952, 143196160,
+ 3625713664, 2813263872, 2000814080, 1188364288,
+ 375914496, 3858432000, 3045982208, 2233532416,
+ 1421082624, 608632832, 4091150336, 3278700544
+};
+
+/*
+ The key for the multiplicative hash function consists of 3 unsigned
+ characters. They are composed (logically) by concatenating them i.e.
+ the composed key = 2^16*c2 + 2^8*c2 + c3 and fits in 24 bits. The
+ composed key is not actually computed here as we use the components
+ to directly compute the hash function.
+
+ The multiplicative hash function consists of taking the higher order
+ 12 bits (2^12 = 4096) of the lower order 24 bits of the product
+ key * Multiplier where
+ Multiplier = floor(A * pow(2.0, (double) w));
+ double A = 0.6125423371; (chosen according to Knuth)
+ w = 24 (the key's width in bits)
+ The algorithm for this is in Cormen/Leiserson/Rivest.
+
+ To do the multplication efficiently, the product c*Multiplier is
+ precomputed and stored in lookup_array1 (for all 256 possible c's).
+ lookup_array2 and lookup_array3 contain the same data as lookup_array1
+ but shifted left 8 and 16 bits respectively.
+
+ MultHash1 is the mult hashing function. MultHash0 contains an older
+ (slower but less space-efficient) version of the same function.
+*/
+
+
+#define MULTHASH1(c1,c2,c3) \
+ ((lookup_array1[c1]+ \
+ lookup_array2[c2]+ \
+ lookup_array3[c3] ) & 0x00fff000) >> 12
+
+
+/*
+USHORT xorlookup1 [256] = {
+ 0x110, 0x120, 0x130, 0x140, 0x150, 0x160, 0x170, 0x180, // 0-7
+ 0x190, 0x1a0, 0x1b0, 0x1c0, 0x1d0, 0x1e0, 0x1f0, 0x100, // 8-15
+ 0x210, 0x220, 0x230, 0x240, 0x250, 0x260, 0x270, 0x280, // 16-23
+ 0x290, 0x2a0, 0x2b0, 0x2c0, 0x2d0, 0x2e0, 0x2f0, 0x200, // 24-31
+ 0x310, 0x320, 0x330, 0x340, 0x350, 0x360, 0x370, 0x380, // 32-39
+ 0x390, 0x3a0, 0x3b0, 0x3c0, 0x3d0, 0x3e0, 0x3f0, 0x300, // 40-47
+ 0x410, 0x420, 0x430, 0x440, 0x450, 0x460, 0x470, 0x480, // 48-55
+ 0x490, 0x4a0, 0x4b0, 0x4c0, 0x4d0, 0x4e0, 0x4f0, 0x400, // 56-63
+ 0x510, 0x520, 0x530, 0x540, 0x550, 0x560, 0x570, 0x580, // 64-71
+ 0x590, 0x5a0, 0x5b0, 0x5c0, 0x5d0, 0x5e0, 0x5f0, 0x500, // 72-79
+ 0x610, 0x620, 0x630, 0x640, 0x650, 0x660, 0x670, 0x680, // 80-87
+ 0x690, 0x6a0, 0x6b0, 0x6c0, 0x6d0, 0x6e0, 0x6f0, 0x600, // 88-95
+ 0x710, 0x720, 0x730, 0x740, 0x750, 0x760, 0x770, 0x780, // 96-103
+ 0x790, 0x7a0, 0x7b0, 0x7c0, 0x7d0, 0x7e0, 0x7f0, 0x700, // 104-111
+ 0x810, 0x820, 0x830, 0x840, 0x850, 0x860, 0x870, 0x880, // 112-119
+ 0x890, 0x8a0, 0x8b0, 0x8c0, 0x8d0, 0x8e0, 0x8f0, 0x800, // 120-127
+ 0x910, 0x920, 0x930, 0x940, 0x950, 0x960, 0x970, 0x980, // 128-135
+ 0x990, 0x9a0, 0x9b0, 0x9c0, 0x9d0, 0x9e0, 0x9f0, 0x900, // 136-143
+ 0xa10, 0xa20, 0xa30, 0xa40, 0xa50, 0xa60, 0xa70, 0xa80, // 144-151
+ 0xa90, 0xaa0, 0xab0, 0xac0, 0xad0, 0xae0, 0xaf0, 0xa00, // 152-159
+ 0xb10, 0xb20, 0xb30, 0xb40, 0xb50, 0xb60, 0xb70, 0xb80, // 160-167
+ 0xb90, 0xba0, 0xbb0, 0xbc0, 0xbd0, 0xbe0, 0xbf0, 0xb00, // 168-175
+ 0xc10, 0xc20, 0xc30, 0xc40, 0xc50, 0xc60, 0xc70, 0xc80, // 176-183
+ 0xc90, 0xca0, 0xcb0, 0xcc0, 0xcd0, 0xce0, 0xcf0, 0xc00, // 184-191
+ 0xd10, 0xd20, 0xd30, 0xd40, 0xd50, 0xd60, 0xd70, 0xd80, // 192-199
+ 0xd90, 0xda0, 0xdb0, 0xdc0, 0xdd0, 0xde0, 0xdf0, 0xd00, // 200-207
+ 0xe10, 0xe20, 0xe30, 0xe40, 0xe50, 0xe60, 0xe70, 0xe80, // 208-215
+ 0xe90, 0xea0, 0xeb0, 0xec0, 0xed0, 0xee0, 0xef0, 0xe00, // 216-223
+ 0xf10, 0xf20, 0xf30, 0xf40, 0xf50, 0xf60, 0xf70, 0xf80, // 224-231
+ 0xf90, 0xfa0, 0xfb0, 0xfc0, 0xfd0, 0xfe0, 0xff0, 0xf00, // 232-239
+ 0x010, 0x020, 0x030, 0x040, 0x050, 0x060, 0x070, 0x080, // 240-247
+ 0x090, 0x0a0, 0x0b0, 0x0c0, 0x0d0, 0x0e0, 0x0f0, 0x000 }; // 248-255
+
+
+USHORT xorlookup2 [256] = {
+ 0x101, 0x201, 0x301, 0x401, 0x501, 0x601, 0x701, 0x801, // 0-7
+ 0x901, 0xa01, 0xb01, 0xc01, 0xd01, 0xe01, 0xf01, 0x001, // 8-15
+ 0x102, 0x202, 0x302, 0x402, 0x502, 0x602, 0x702, 0x802, // 16-23
+ 0x902, 0xa02, 0xb02, 0xc02, 0xd02, 0xe02, 0xf02, 0x002, // 24-31
+ 0x103, 0x203, 0x303, 0x403, 0x503, 0x603, 0x703, 0x803, // 32-39
+ 0x903, 0xa03, 0xb03, 0xc03, 0xd03, 0xe03, 0xf03, 0x003, // 40-47
+ 0x104, 0x204, 0x304, 0x404, 0x504, 0x604, 0x704, 0x804, // 48-55
+ 0x904, 0xa04, 0xb04, 0xc04, 0xd04, 0xe04, 0xf04, 0x004, // 56-63
+ 0x105, 0x205, 0x305, 0x405, 0x505, 0x605, 0x705, 0x805, // 64-71
+ 0x905, 0xa05, 0xb05, 0xc05, 0xd05, 0xe05, 0xf05, 0x005, // 72-79
+ 0x106, 0x206, 0x306, 0x406, 0x506, 0x606, 0x706, 0x806, // 80-87
+ 0x906, 0xa06, 0xb06, 0xc06, 0xd06, 0xe06, 0xf06, 0x006, // 88-95
+ 0x107, 0x207, 0x307, 0x407, 0x507, 0x607, 0x707, 0x807, // 96-103
+ 0x907, 0xa07, 0xb07, 0xc07, 0xd07, 0xe07, 0xf07, 0x007, // 104-111
+ 0x108, 0x208, 0x308, 0x408, 0x508, 0x608, 0x708, 0x808, // 112-119
+ 0x908, 0xa08, 0xb08, 0xc08, 0xd08, 0xe08, 0xf08, 0x008, // 120-127
+ 0x109, 0x209, 0x309, 0x409, 0x509, 0x609, 0x709, 0x809, // 128-135
+ 0x909, 0xa09, 0xb09, 0xc09, 0xd09, 0xe09, 0xf09, 0x009, // 136-143
+ 0x10a, 0x20a, 0x30a, 0x40a, 0x50a, 0x60a, 0x70a, 0x80a, // 144-151
+ 0x90a, 0xa0a, 0xb0a, 0xc0a, 0xd0a, 0xe0a, 0xf0a, 0x00a, // 152-159
+ 0x10b, 0x20b, 0x30b, 0x40b, 0x50b, 0x60b, 0x70b, 0x80b, // 160-167
+ 0x90b, 0xa0b, 0xb0b, 0xc0b, 0xd0b, 0xe0b, 0xf0b, 0x00b, // 168-175
+ 0x10c, 0x20c, 0x30c, 0x40c, 0x50c, 0x60c, 0x70c, 0x80c, // 176-183
+ 0x90c, 0xa0c, 0xb0c, 0xc0c, 0xd0c, 0xe0c, 0xf0c, 0x00c, // 184-191
+ 0x10d, 0x20d, 0x30d, 0x40d, 0x50d, 0x60d, 0x70d, 0x80d, // 192-199
+ 0x90d, 0xa0d, 0xb0d, 0xc0d, 0xd0d, 0xe0d, 0xf0d, 0x00d, // 200-207
+ 0x10e, 0x20e, 0x30e, 0x40e, 0x50e, 0x60e, 0x70e, 0x80e, // 208-215
+ 0x90e, 0xa0e, 0xb0e, 0xc0e, 0xd0e, 0xe0e, 0xf0e, 0x00e, // 216-223
+ 0x10f, 0x20f, 0x30f, 0x40f, 0x50f, 0x60f, 0x70f, 0x80f, // 224-231
+ 0x90f, 0xa0f, 0xb0f, 0xc0f, 0xd0f, 0xe0f, 0xf0f, 0x00f, // 232-239
+ 0x000, 0x200, 0x300, 0x400, 0x500, 0x600, 0x700, 0x800, // 240-247
+ 0x900, 0xa00, 0xb00, 0xc00, 0xd00, 0xe00, 0xf00, 0x100 }; // 248-255
+
+*/
+
+/* Bitptrs point to the current byte. The current bit (i.e. next bit to be
+ * stored) is masked off by the bit entry. When this reaches zero, it is
+ * reset to 0x80 and the next byte is set up. The bytes are filled MSBit
+ * first. */
+
+/* Starts and sets the first byte to zero for the bitptr. */
+#define bitptr_init(s) pbyte = s; byte=0; bit = 16;
+
+/* Sets up the byte part of the bitptr so that it is pointing to the byte after
+ * the byte which had the last bit put into it. */
+#define bitptr_end() if (bit != 16) *pbyte++=(UCHAR)(byte >> 8);
+
+/* Goes to the next bit, and byte if necessary. */
+#define bitptr_next() \
+ if (bit < 10) { \
+ *pbyte++=(UCHAR)(byte >> 8); \
+ byte <<= 8; \
+ bit = 16; \
+ } else \
+ bit-- ;
+
+/*
+#define bitptr_next() \
+ bit--; \
+ if (bit < 9) { \
+ *pbyte++=(UCHAR)(byte >> 8); \
+ byte <<= 8; \
+ bit = 16; \
+ }
+*/
+
+
+/* Advances to the next bit, and byte if necessary, readjusting the bit. */
+#define bitptr_advance() \
+ if (bit < 9) { \
+ *pbyte++=(UCHAR)(byte >> 8); \
+ bit+=8; \
+ byte <<= 8; \
+ }
+
+
+/* BIT I/O FUNCTIONS *********************************************************/
+
+/* These routines output most-significant-bit-first and the input will return
+ * them MSB first, too. */
+
+/* Outputs a one bit in the bit stream. */
+#define out_bit_1() bit--; byte |= (1 << bit); bitptr_advance();
+#define out_bit_0() bitptr_next();
+
+/* TestBit; output 1 if that bit is set */
+//#define tb(b,w,n) if ((w) & (n)) *pbyte |= bit; bitptr_next(b);
+
+#define out_bits_2(w) bit-=2; byte|=(w << bit); bitptr_advance();
+#define out_bits_3(w) bit-=3; byte|=(w << bit); bitptr_advance();
+#define out_bits_4(w) bit-=4; byte|=(w << bit); bitptr_advance();
+#define out_bits_5(w) bit-=5; byte|=(w << bit); bitptr_advance();
+#define out_bits_6(w) bit-=6; byte|=(w << bit); bitptr_advance();
+#define out_bits_7(w) bit-=7; byte|=(w << bit); bitptr_advance();
+
+// #define out_bits_8(w) bit-=8; byte|=(w << bit); bit+=8; *pbyte++=(UCHAR)(byte >> 8); byte <<= 8;
+#define out_bits_8(w) byte|=(w << (bit-8)); *pbyte++=(UCHAR)(byte >> 8); byte <<= 8;
+
+
+/*
+#define out_bits_9(w) \
+ if (bit > 9) { \
+ bit-=9; byte|=(w << bit); \
+ *pbyte++=(UCHAR)(byte >> 8);\
+ bit+=8; \
+ byte <<= 8; \
+ } else { \
+ bit=16; byte |= w; \
+ *pbyte++=(UCHAR)(byte >> 8); *pbyte++=(UCHAR)(byte); byte=0; \
+ }
+*/
+
+#define out_bits_9(w) \
+ if (bit > 9) { \
+ byte|=(w << (bit-9)); \
+ *pbyte++=(UCHAR)(byte >> 8);\
+ bit--; \
+ byte <<= 8; \
+ } else { \
+ bit=16; byte |= w; \
+ *pbyte++=(UCHAR)(byte >> 8); *pbyte++=(UCHAR)(byte); byte=0; \
+ }
+
+
+#define out_bits_10(w) \
+ if (bit > 10) { \
+ bit-=10; byte |= (w << bit); *pbyte++ = (UCHAR)(byte >> 8); bit+=8; byte <<=8; \
+ } else { \
+ out_bits_2((w >> 8)); \
+ out_bits_8((w & 0xFF)); \
+ }
+
+//
+// Weird effect - if out_bits_9 used instead of out_bits_8,
+// it's faster! if (bit == 11) is faster than if (bit != 11).
+//
+
+#define out_bits_11(w) \
+ if (bit > 11) { \
+ bit-=11; byte |= (w << bit); *pbyte++ = (UCHAR)(byte >> 8); bit+=8; byte <<=8; \
+ } else { \
+ if (bit == 11) { \
+ bit=16; byte |= w; \
+ *pbyte++=(UCHAR)(byte >> 8); *pbyte++=(UCHAR)(byte); byte=0; \
+ } else { \
+ bit=11-bit; \
+ byte|=(w >> bit); \
+ *pbyte++=(UCHAR)(byte >> 8); *pbyte++=(UCHAR)(byte); \
+ bit=16-bit; \
+ byte=(w << bit); \
+ } \
+ }
+
+
+#define out_bits_12(w) \
+ if (bit > 12) { \
+ bit-=12; byte |= (w << bit); *pbyte++ = (UCHAR)(byte >> 8); bit+=8; byte <<=8; \
+ } else { \
+ out_bits_4((w >> 8)); \
+ out_bits_8((w & 0xFF)); \
+ }
+
+#define out_bits_13(w) \
+ if (bit > 13) { \
+ bit-=13; byte |= (w << bit); *pbyte++ = (UCHAR)(byte >> 8); bit+=8; byte <<=8; \
+ } else { \
+ out_bits_5((w >> 8)); \
+ out_bits_8((w & 0xFF)); \
+ }
+
+#define out_bits_14(w) \
+ if (bit > 14) { \
+ bit-=14; byte |= (w << bit); *pbyte++ = (UCHAR)(byte >> 8); bit+=8; byte <<=8; \
+ } else { \
+ out_bits_6((w >> 8)); \
+ out_bits_8((w & 0xFF)); \
+ }
+
+
+#define out_reserve_4() \
+ bit-=4; bitptr_advance();
+
+
+/* Starts the given bit pointer */
+#define inbit_start(s) pbyte = s; bit = 16; byte=(*pbyte << 8) + *(pbyte+1); pbyte++;
+#define inbit_end() if (bit != 16) pbyte++;
+
+#define in_bit_next() if (bit < 9) { \
+ bit=16; \
+ byte <<=8; \
+ byte |= *(++pbyte); \
+ }
+
+
+#define in_bit_advance() if (bit < 9) { \
+ bit+=8; \
+ byte <<=8; \
+ byte |= *(++pbyte); \
+ }
+
+/* Returns non-zero in bitset if the next bit in the stream is a 1. */
+#define in_bit() bit--; bitset = (byte >> bit) & 1; in_bit_next()
+
+
+#define in_bits_2(w) bit-=2; w = (byte >> bit) & 0x03;\
+ in_bit_advance();
+
+#define in_bits_3(w) bit-=3; w = (byte >> bit) & 0x07;\
+ in_bit_advance();
+
+#define in_bits_4(w) bit-=4; w = (byte >> bit) & 0x0F;\
+ in_bit_advance();
+
+#define in_bits_5(w) bit-=5; w = (byte >> bit) & 0x1F;\
+ in_bit_advance();
+
+#define in_bits_6(w) bit-=6; w = (byte >> bit) & 0x3F;\
+ in_bit_advance();
+
+#define in_bits_7(w) bit-=7; w = (byte >> bit) & 0x7F;\
+ in_bit_advance();
+
+#define in_bits_8(w) bit-=8; w = (byte >> bit) & 0xFF;\
+ bit+=8; byte <<=8; byte |= *(++pbyte);
+
+
+#define in_bits_9(w) bit-=9; w = (byte >> bit) & 0x1FF; \
+ bit+=8; byte <<=8; byte |= *(++pbyte); \
+ in_bit_advance();
+
+#define in_bits_10(w) if (bit > 10) { \
+ bit-=10; w = (byte >> bit) & 0x3FF; \
+ bit+=8; byte <<=8; byte |= *(++pbyte); \
+ } else { \
+ in_bits_2(bitset); \
+ in_bits_8(w); \
+ w= w + (bitset << 8); \
+ }
+
+#define in_bits_11(w) if (bit > 11) { \
+ bit-=11; w = (byte >> bit) & 0x7FF; \
+ bit+=8; byte <<=8; byte |= *(++pbyte); \
+ } else { \
+ in_bits_3(bitset); \
+ in_bits_8(w); \
+ w= w + (bitset << 8); \
+ }
+
+
+#define in_bits_12(w) if (bit > 12) { \
+ bit-=12; w = (byte >> bit) & 0xFFF; \
+ bit+=8; byte <<=8; byte |= *(++pbyte); \
+ } else { \
+ in_bits_4(bitset); \
+ in_bits_8(w); \
+ w= w + (bitset << 8); \
+ }
+
+
+
+#define in_bits_13(w)\
+ if (bit > 13) { \
+ bit-=13; w = (byte >> bit) & 0x1FFF; \
+ bit+=8; byte <<=8; byte |= *(++pbyte); \
+ } else { \
+ in_bits_5(bitset); \
+ in_bits_8(w); \
+ w=w + (bitset << 8); \
+ }
+
+
+#define in_bits_14(w)\
+ if (bit > 14) { \
+ bit-=14; w = (byte >> bit) & 0x3FFF; \
+ bit+=8; byte <<=8; byte |= *(++pbyte); \
+ } else { \
+ in_bits_6(bitset); \
+ in_bits_8(w); \
+ w=w + (bitset << 8); \
+ }
+
+
+
+UCHAR SHApad1[40] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+UCHAR SHApad2[40] = {0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2,
+ 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2,
+ 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2,
+ 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2, 0xF2};
+
+#ifdef DEBUG
+char
+ChPrint(UCHAR b)
+{
+ if (isprint(b))
+ return (char)b;
+ else
+ return '.';
+}
+#endif
+
+
+//* compress()
+//
+// Function: Main compression function.
+//
+// Parameters:
+// IN CurrentBuffer -> points to NDIS_WAN_PACKET with data to compress
+// OUT CompOutBuffer -> points to NDIS_WAN_PACKET to compress data to
+// IN CurrentLength -> points to Length of data to compress
+// IN context -> connection compress context
+//
+// Returns: Nothing
+//
+// WARNING: CODE IS HIGHLY OPTIMIZED FOR TIME.
+//
+//
+UCHAR
+compress (UCHAR *CurrentBuffer, UCHAR *CompOutBuffer, ULONG *CurrentLength, SendContext *context)
+{
+ int copylen ;
+ int bit;
+ int byte;
+ int backptr ;
+ int cbMatch;
+ int hashvalue ;
+ int lookup1 ;
+ UCHAR *matchptr ;
+ UCHAR *pbyte;
+ UCHAR *historyptr ;
+ UCHAR *currentptr ;
+ UCHAR *endptr ;
+ UCHAR hashchar1;
+ UCHAR hashchar2;
+ UCHAR hashchar3;
+ int literal ;
+ UCHAR status=0; // return flags
+ PUCHAR currentbuf ;
+
+
+ // Will this packet fit at the end of the history buffer?
+ //
+ if (((context->CurrentIndex + *CurrentLength) >= (HISTORY_MAX - 1 )) ||
+ (context->CurrentIndex == 0)) {
+ context->CurrentIndex = 0; // Index into the history
+ status |= PACKET_AT_FRONT;
+ }
+
+ //
+ // we no longer need to save the non compressed data - tonybe 01-12-95
+ //
+// RtlMoveMemory(context->CompressBuffer, CurrentBuffer, *CurrentLength) ;
+
+ // Start out the bit pointing output
+ //
+ bitptr_init(CompOutBuffer);
+
+ //
+ // We are now compressing into an output buffer - tonybe 01-12-95
+ //
+// bitptr_init(CurrentBuffer);
+
+ historyptr = context->History + context->CurrentIndex ;
+
+ currentptr = CurrentBuffer;
+
+ //
+ // we are now compressing from the currentbuffer - tonybe 01-12-95
+ //
+// currentptr = context->CompressBuffer ;
+
+ endptr = currentptr + *CurrentLength - 1;
+
+ while (currentptr < (endptr-2)) {
+
+ *historyptr++ = hashchar1 = *currentptr++ ;
+ hashchar2 = *currentptr ;
+ hashchar3 = *(currentptr+1) ;
+
+ // "fast" hash function
+ // hashvalue = (int)hashchar1 ^ xorlookup1[hashchar2] ^ xorlookup2[hashchar3];
+ hashvalue = MULTHASH1(hashchar1, hashchar2, hashchar3) ;
+
+ matchptr = context->History + context->HashTable[hashvalue] ;
+
+ if (matchptr != (historyptr - 1))
+ context->HashTable[hashvalue] = historyptr - context->History ;
+
+ if (context->ValidHistory < historyptr)
+ context->ValidHistory = historyptr ;
+
+ if (matchptr != context->History &&
+ *(matchptr-1) == hashchar1 && *matchptr == hashchar2 &&
+ *(matchptr+1) == hashchar3 && matchptr != (historyptr - 1) &&
+ matchptr != historyptr && (matchptr+1) <= context->ValidHistory) {
+
+ backptr = (historyptr - matchptr) & (HISTORY_SIZE - 1) ;
+
+ *historyptr++ = hashchar2 ; // copy the other 2 chars
+ *historyptr++ = hashchar3 ; // copy the other 2 chars
+ currentptr +=2 ;
+ cbMatch = 3 ; // length of match
+ matchptr +=2 ; // we have already matched 3
+
+ while ((*matchptr == *currentptr) && (currentptr < endptr) && (matchptr <= context->ValidHistory)) {
+ matchptr++ ;
+ *historyptr++ = *currentptr++ ;
+ cbMatch++ ;
+ }
+
+#ifdef DEBUG
+ DbgPrint("\tCOMP: Location:%d Char %c, matched length %d, backindex %d\n", (currentptr - context->CompressBuffer), ChPrint(*currentptr), cbMatch, backptr) ;
+#endif
+
+ // First output the backpointer
+ //
+ if (backptr >= 320) {
+ backptr -= 320 ;
+ out_bits_8((0xc000 + backptr) >> 8) ; // 110 + 13 bits
+ out_bits_8((backptr)) ;
+ } else if (backptr < 64) { // 1111 + 6 bits
+ backptr += 0x3c0 ;
+ out_bits_10(backptr);
+ } else {
+ backptr += (0xE00 - 64); // 1110 + 8 bits
+ out_bits_12(backptr);
+ }
+
+ // output the length of the match encoding
+ //
+ switch (cbMatch) {
+
+ case 3:
+ out_bit_0(); // length of 3 - most common
+ break;
+
+ case 4:
+ out_bits_4(8);
+ break;
+
+ case 5:
+ out_bits_4(9);
+ break;
+
+ case 6:
+ out_bits_4(10);
+ break;
+
+ case 7:
+ out_bits_4(11);
+ break;
+
+ case 8:
+ out_bits_6(48);
+ break;
+
+ case 9:
+ out_bits_6(49);
+ break;
+
+ case 10:
+ out_bits_6(50);
+ break;
+
+ case 11:
+ out_bits_6(51);
+ break;
+
+ case 12:
+ out_bits_6(52);
+ break;
+
+ case 13:
+ out_bits_6(53);
+ break;
+
+ case 14:
+ out_bits_6(54);
+ break;
+
+ case 15:
+ out_bits_6(55);
+ break;
+
+ case 16:
+ out_bits_8(0xe0);
+ break;
+
+ case 17:
+ out_bits_8(0xe1);
+ break;
+
+ case 18:
+ out_bits_8(0xe2);
+ break;
+
+ case 19:
+ out_bits_8(0xe3);
+ break;
+
+ case 20:
+ out_bits_8(0xe4);
+ break;
+
+ case 21:
+ out_bits_8(0xe5);
+ break;
+
+ case 22:
+ out_bits_8(0xe6);
+ break;
+
+ case 23:
+ out_bits_8(0xe7);
+ break;
+
+ case 24:
+ out_bits_8(0xe8);
+ break;
+
+ case 25:
+ out_bits_8(0xe9);
+ break;
+
+ case 26:
+ out_bits_8(0xea);
+ break;
+
+ case 27:
+ out_bits_8(0xeb);
+ break;
+
+ case 28:
+ out_bits_8(0xec);
+ break;
+
+ case 29:
+ out_bits_8(0xed);
+ break;
+
+ case 30:
+ out_bits_8(0xee);
+ break;
+
+ case 31:
+ out_bits_8(0xef);
+ break;
+
+ default:
+ if (cbMatch < 64) {
+ out_bits_4(0xF) ;
+ cbMatch -= 32 ;
+ out_bits_6(cbMatch) ;
+ }
+ else if (cbMatch < 128) {
+ out_bits_5(0x1F) ;
+ cbMatch -= 64 ;
+ out_bits_7(cbMatch) ;
+ }
+ else if (cbMatch < 256) {
+ out_bits_6(0x3F) ;
+ cbMatch -= 128 ;
+ out_bits_8(cbMatch) ;
+ }
+ else if (cbMatch < 512) {
+ out_bits_7(0x7F) ;
+ cbMatch -= 256 ;
+ out_bits_9(cbMatch) ;
+ }
+ else if (cbMatch < 1024) {
+ out_bits_8(0xFF) ;
+ cbMatch -= 512 ;
+ out_bits_10(cbMatch) ;
+ }
+ else if (cbMatch < 2048) {
+ out_bits_9(0x1FF) ;
+ cbMatch -= 1024 ;
+ out_bits_11(cbMatch) ;
+ }
+ else if (cbMatch < 4096) {
+ out_bits_10(0x3FF) ;
+ cbMatch -= 2048 ;
+ out_bits_12(cbMatch) ;
+ }
+ else if (cbMatch < 8192) {
+ out_bits_11(0x7FF) ;
+ cbMatch -= 4096 ;
+ out_bits_13(cbMatch) ;
+ }
+ else { // 8192 and greater
+ out_bits_12(0xFFF) ;
+ cbMatch -= 8192 ;
+ out_bits_14(cbMatch) ;
+ }
+ break ;
+ }
+
+ } else { // encode a literal
+
+#ifdef DEBUG
+ DbgPrint("\t COMP:Location %d, <No Match>: '%c'\n", (currentptr - context->CompressBuffer),*currentptr) ;
+#endif
+ // temp=literallookup[context->History[i-1]] ;
+ literal= hashchar1 ;
+
+ if (literal & 0x80) {
+ literal += 0x80;
+ out_bits_9(literal) ;
+ } else {
+ out_bits_8(literal) ;
+ }
+
+ }
+
+ } // while
+
+
+ // get any remaining chars as literals
+ while (currentptr <= endptr) {
+
+#ifdef DEBUG
+ DbgPrint("\t COMP:Location %d, <No Match>: '%c'\n", (currentptr - context->CompressBuffer),*currentptr) ;
+#endif
+
+ // temp=literallookup[context->History[i-1]] ;
+ literal=*currentptr ;
+
+
+ if (literal & 0x80) {
+ literal += 0x80;
+ out_bits_9(literal) ;
+ } else {
+ out_bits_8(literal) ;
+ }
+
+ *historyptr++ = *currentptr++ ;
+ }
+
+
+ bitptr_end() ;
+
+
+ // Check if we had expansion instead of compression
+ //
+ if ((ULONG)(pbyte - CompOutBuffer) > *CurrentLength) { // expansion.
+
+ //
+ // We don't need to do this copy since we can just signal the outside world
+ // that compression did not take place and the valid data is still in the
+ // current buffer
+ //
+ // RtlMoveMemory(CompOutBuffer, CurrentBuffer, *CurrentLength) ;
+
+ memset (context->History, 0, sizeof(context->History)) ;
+ memset (context->HashTable, 0, sizeof(context->HashTable)) ;
+#ifdef COMP_12K
+ status = 0 ;
+#else
+ status = PACKET_FLUSHED;
+#endif
+ context->CurrentIndex = HISTORY_SIZE+1 ; // this forces a start over next time
+
+ } else { // compression successful
+
+ *CurrentLength = pbyte - CompOutBuffer;
+
+ //
+ // the compressed data is now in CompOutBuffer - tonybe 01-12-95
+ //
+ // *CurrentLength = pbyte - CurrentBuffer ;
+
+ status |= PACKET_COMPRESSED ;
+ context->CurrentIndex = historyptr - context->History ;
+ }
+
+ return(status);
+}
+
+
+
+//* getcontextsizes()
+//
+// Function: Returns size of send and receive context blocks
+//
+// Parameters: OUT send -> sizeof(SendContext)
+// OUT recv -> sizeof(RecvContext)
+//
+// Returns: Nothing
+//
+//*
+void
+getcontextsizes (long *send, long *recv)
+{
+ *send = sizeof(SendContext) ;
+ *recv = sizeof(RecvContext) ;
+}
+
+
+//* initsendcontext()
+//
+// Function: Initialize SendContext block
+//
+// Parameters: IN context -> connection compress context
+//
+// Returns: Nothing
+//
+//*
+void
+initsendcontext (SendContext *context)
+{
+ context->CurrentIndex = 0; // Index into the history
+ context->ValidHistory = 0 ; // reset valid history
+ memset (context->HashTable, 0, sizeof(context->HashTable)) ;
+ memset (context->History, 0, sizeof(context->HashTable)) ;
+}
+
+
+
+//* initrecvcontext()
+//
+// Function: Initialize RecvContext block
+//
+// Parameters: IN context -> connection decompress context
+//
+// Returns: Nothing
+//
+//*
+void
+initrecvcontext (RecvContext *context)
+{
+ context->CurrentPtr = context->History ;
+
+#if DBG
+ context->DebugFence = DEBUG_FENCE_VALUE;
+#endif
+
+ memset (context->History, 0, sizeof(context->History)) ;
+}
+
+
+
+//* decompress()
+//
+// Function: de-compression function.
+//
+// Parameters: IN inbuf -> points to data to be uncompressed
+// IN inlen -> length of data
+// IN start -> flag indicating whether to start with a clean history buffer
+// OUT output-> decompressed data
+// OUT outlen-> lenght of decompressed data
+// IN context -> connection decompress context
+//
+// Returns: TRUE if decompress was successful
+// FALSE if it wasnt
+//
+// WARNING: CODE IS HIGHLY OPTIMIZED FOR TIME.
+//
+//*
+int
+decompress(
+ UCHAR *inbuf,
+ int inlen,
+ int start,
+ UCHAR **output,
+ int *outlen,
+ RecvContext *context)
+{
+ UCHAR *inend; // When we know we're done decompressing
+ UCHAR *outstart; // Remember where in dbuf we started
+
+ UCHAR *current;
+
+ int backptr; // Back pointer for copy items
+ int length; // Where to copy from in dbuf
+
+ UCHAR *s1, *s2;
+
+ int bitset;
+ int bit;
+ int byte;
+ UCHAR *pbyte;
+ UCHAR *historyend = context->History + HISTORY_SIZE ;
+
+ inend = inbuf + inlen ;
+
+ //
+ // Start out looking at the first bit
+ //
+ inbit_start(inbuf);
+
+ if (start) // start over clean?
+ context->CurrentPtr = current = context->History ;
+ else
+ current = context->CurrentPtr ;
+
+ //
+ // Save our starting position
+ //
+ outstart = current;
+
+ //
+ // Decompress until we run out of input
+ //
+ while (pbyte < inend) {
+
+ //
+ // Jump on what to do with these three bits.
+ //
+ in_bits_3(length);
+
+ switch (length) {
+
+ case 0:
+ in_bits_5(length) ;
+ goto LITERAL ;
+
+ case 1:
+ in_bits_5(length) ;
+ length += 32 ;
+ goto LITERAL ;
+
+ case 2:
+ in_bits_5(length) ;
+ length += 64 ;
+ goto LITERAL ;
+
+ case 3:
+ in_bits_5(length) ;
+ length += 96 ;
+ goto LITERAL ;
+
+ case 4:
+ in_bits_6(length) ;
+ length +=128 ;
+ goto LITERAL ;
+
+ case 5:
+ in_bits_6(length) ;
+ length +=192 ;
+ goto LITERAL ;
+
+ case 6:
+ in_bits_13 (backptr) ; // 110 - 14 bit offset
+ backptr+=320 ;
+ break ;
+
+ case 7:
+ in_bit() ;
+ if (bitset) {
+ in_bits_6(backptr) ;
+ } else {
+ in_bits_8(backptr) ;
+ backptr+=64 ;
+ }
+ break ;
+ }
+
+ //
+ // If we reach here, it's a copy item
+ //
+
+ //
+ // Now get the length
+ //
+
+ in_bit() ; // 1st length bit
+ if (!bitset) {
+ length = 3 ;
+ goto DONE ;
+ }
+
+ in_bit() ; // 2nd length bit
+ if (!bitset) {
+ in_bits_2 (length) ;
+ length += 4 ;
+ goto DONE ;
+ }
+
+ in_bit() ; // 3rd length bit
+ if (!bitset) {
+ in_bits_3 (length) ;
+ length += 8 ;
+ goto DONE ;
+ }
+
+ in_bit() ; // 4th length bit
+ if (!bitset) {
+ in_bits_4 (length) ;
+ length += 16 ;
+ goto DONE ;
+ }
+
+ in_bit() ; // 5th length bit
+ if (!bitset) {
+ in_bits_5 (length) ;
+ length += 32 ;
+ goto DONE ;
+ }
+
+ in_bit() ; // 6th length bit
+ if (!bitset) {
+ in_bits_6 (length) ;
+ length += 64 ;
+ goto DONE ;
+ }
+
+ in_bit() ; // 7th length bit
+ if (!bitset) {
+ in_bits_7 (length) ;
+ length += 128 ;
+ goto DONE ;
+ }
+
+ in_bit() ; // 8th length bit
+ if (!bitset) {
+ in_bits_8 (length) ;
+ length += 256 ;
+ goto DONE ;
+ }
+
+ in_bit() ; // 9th length bit
+ if (!bitset) {
+ in_bits_9 (length) ;
+ length += 512 ;
+ goto DONE ;
+ }
+
+ in_bit() ; // 10th length bit
+ if (!bitset) {
+ in_bits_10 (length) ;
+ length += 1024 ;
+ goto DONE ;
+ }
+
+ //
+ // length cannot be greater than max packets size which is 1500
+ //
+ DbgPrint("NDISWAN: RAS Decompressor problem: Possible data corruption\n");
+
+ return FALSE ;
+
+
+ DONE:
+ //
+ // Turn the backptr into an index location
+ //
+#ifdef COMP_12K
+ s2 = current - backptr ;
+#else
+ s2 = context->History + (((current - context->History) - backptr) & (HISTORY_SIZE -1)) ;
+#endif
+
+ s1 = current;
+
+#ifdef DEBUG
+ DbgPrint("\tdecomp: location: %d, bp %.4d length %.4d\n", (current-context->CurrentPtr), backptr, length);
+#endif
+ current += length;
+
+ // if we are past the end of the history this is a bad sign: abort decompression
+ //
+ if (current >= historyend) {
+ DbgPrint("NDISWAN: RAS Decompressor problem: Possible data corruption\n");
+ return FALSE ;
+ }
+
+ // loop unrolled to handle lenght>backptr case
+ //
+ *s1=*s2;
+ *(s1+1)=*(s2+1);
+ s1+=2;
+ s2+=2;
+ length-=2;
+
+ //
+ // copy all the bytes
+ //
+ while (length) {
+ *s1++=*s2++;
+ length--;
+ }
+
+ //
+ // We have another copy item, and no literals
+ //
+ continue;
+
+
+ LITERAL:
+
+#ifdef DEBUG
+ DbgPrint("\tdecomp: Location %d, literal '%c'\n",(current-context->CurrentPtr), length);
+#endif
+
+ //
+ // We have a literal
+ //
+ //*current++ = literallookup[length];
+ *current++ = length;
+
+ } // while loop
+
+
+ // End case:
+ //
+ if ((bit == 16) && (pbyte == inend)) {
+ *current++ = *(pbyte -1) ;
+ }
+
+#if DBG
+ if (context->DebugFence != DEBUG_FENCE_VALUE) {
+ DbgPrint("Decompression Error!\n");
+ DbgPrint("context 0x%8.8x, current 0x%8.8x, outstart 0x%8.8x\n", context, current, outstart);
+ DbgPrint("inbuf 0x%8.8x, inlength %d, start 0x%8.8x\n", inbuf, inlen, start);
+ DbgBreakPoint();
+ }
+#endif
+
+ *outlen = current - outstart ; // the length of decompressed data
+
+ *output = context->CurrentPtr ;
+
+ context->CurrentPtr = current ;
+
+ return TRUE ;
+}
+
+NDIS_STATUS
+InitSHAContext(
+ PENCRYPTION_INFO EncryptInfo
+ )
+{
+ if (EncryptInfo->Context == NULL) {
+ NdisWanAllocateMemory(&EncryptInfo->Context, sizeof(A_SHA_CTX));
+
+ if (EncryptInfo->Context == NULL) {
+ return (NDIS_STATUS_RESOURCES);
+ }
+ }
+
+ return (NDIS_STATUS_SUCCESS);
+}
+
+//
+// This function uses the 16 byte user session key and the 8 byte
+// challenge to create an intial 16 byte encryption session key.
+//
+VOID
+GetStartKeyFromSHA(
+ PENCRYPTION_INFO EncryptInfo,
+ PUCHAR Challenge
+ )
+{
+ UCHAR Digest[A_SHA_DIGEST_LEN];
+ UCHAR SessionKeyChallenge[MAX_USERSESSIONKEY_SIZE + MAX_CHALLENGE_SIZE];
+
+ NdisZeroMemory(Digest, A_SHA_DIGEST_LEN);
+
+ //
+ // Copy the start session key
+ //
+ NdisMoveMemory(SessionKeyChallenge,
+ EncryptInfo->StartKey,
+ EncryptInfo->SessionKeyLength);
+
+ //
+ // Append the challenge
+ //
+ NdisMoveMemory((PUCHAR)(SessionKeyChallenge + EncryptInfo->SessionKeyLength),
+ Challenge,
+ MAX_CHALLENGE_SIZE);
+
+//
+// SHAInit(context)
+// SHAUpdate(context, sessionkey, sessionkeylength)
+// SHAUpdate(context, sessionkeychallenge, sessionkeylength + challengelength)
+// SHAFinal(context, digest)
+//
+// Start key is the first 16 bytes of the digest.
+//
+ A_SHAInit(EncryptInfo->Context);
+
+ A_SHAUpdate(EncryptInfo->Context,
+ EncryptInfo->StartKey,
+ EncryptInfo->SessionKeyLength);
+
+ A_SHAUpdate(EncryptInfo->Context,
+ SessionKeyChallenge,
+ EncryptInfo->SessionKeyLength + MAX_CHALLENGE_SIZE);
+
+ A_SHAFinal(EncryptInfo->Context,
+ Digest);
+
+ NdisMoveMemory(EncryptInfo->StartKey,
+ Digest,
+ EncryptInfo->SessionKeyLength);
+
+ NdisMoveMemory(EncryptInfo->SessionKey,
+ Digest,
+ EncryptInfo->SessionKeyLength);
+}
+
+VOID
+GetNewKeyFromSHA(
+ PENCRYPTION_INFO EncryptInfo
+ )
+{
+ UCHAR Digest[A_SHA_DIGEST_LEN];
+
+ NdisZeroMemory(Digest, A_SHA_DIGEST_LEN);
+
+ A_SHAInit(EncryptInfo->Context);
+ A_SHAUpdate(EncryptInfo->Context,
+ EncryptInfo->StartKey,
+ EncryptInfo->SessionKeyLength);
+ A_SHAUpdate(EncryptInfo->Context,
+ SHApad1,
+ 40);
+ A_SHAUpdate(EncryptInfo->Context,
+ EncryptInfo->SessionKey,
+ EncryptInfo->SessionKeyLength);
+ A_SHAUpdate(EncryptInfo->Context,
+ SHApad2,
+ 40);
+ A_SHAFinal(EncryptInfo->Context,
+ Digest);
+
+ NdisMoveMemory(EncryptInfo->SessionKey,
+ Digest,
+ EncryptInfo->SessionKeyLength);
+}
+
+/* Copyright (C) RSA Data Security, Inc. created 1993. This is an
+ unpublished work protected as such under copyright law. This work
+ contains proprietary, confidential, and trade secret information of
+ RSA Data Security, Inc. Use, disclosure or reproduction without the
+ express written authorization of RSA Data Security, Inc. is
+ prohibited.
+ */
+
+/* SHA initialization. Begins an SHA operation, writing a new context.
+ */
+void A_SHAInitCommon (context)
+A_SHA_COMM_CTX *context;
+{
+ context->count[0] = context->count[1] = 0;
+
+ /* Load magic initialization constants.
+ */
+ context->state[0] = 0x67452301;
+ context->state[1] = 0xefcdab89;
+ context->state[2] = 0x98badcfe;
+ context->state[3] = 0x10325476;
+ context->state[4] = 0xc3d2e1f0;
+}
+
+/* SHA block update operation. Continues an SHA message-digest
+ operation, processing another message block, and updating the
+ context.
+ */
+void A_SHAUpdateCommon (context, partIn, partInLen, Transform)
+A_SHA_COMM_CTX *context;
+unsigned char *partIn;
+ULONG partInLen;
+A_SHA_TRANSFORM *Transform;
+{
+ unsigned int bufferLen;
+
+ /* Compute length of buffer */
+ bufferLen = (unsigned int)(context->count[1] & 0x3f);
+
+ /* Update number of bytes */
+ if ((context->count[1] += partInLen) < partInLen)
+ context->count[0]++;
+
+ /* If previous input in buffer, buffer new input and transform if
+ possible.
+ */
+ if (bufferLen > 0 && bufferLen + partInLen >= 64) {
+ NdisMoveMemory(context->buffer+bufferLen, partIn, 64-bufferLen);
+ partIn += (64-bufferLen);
+ partInLen -= (64-bufferLen);
+ (*Transform) (context->state, context->buffer);
+ bufferLen = 0;
+ }
+
+ /* Transform directly from input.
+ */
+ while (partInLen >= 64) {
+ (*Transform) (context->state, partIn);
+ partIn += 64;
+ partInLen -= 64;
+ }
+
+ /* Buffer remaining input */
+ NdisMoveMemory((context->buffer+bufferLen), partIn, partInLen);
+}
+
+/* SHA finalization. Ends an SHA message-digest operation, writing
+ the message digest and zeroizing the context.
+ */
+void A_SHAFinalCommon (context, digest, Transform)
+A_SHA_COMM_CTX *context;
+unsigned char digest[A_SHA_DIGEST_LEN];
+A_SHA_TRANSFORM *Transform;
+{
+ ULONG bitCount[2];
+ unsigned char pad[72];
+ unsigned int padLen;
+
+ /* Compute padding: 80 00 00 ... 00 00 <bit count>
+ */
+ padLen = 64 - (unsigned int)(context->count[1] & 0x3f);
+ if (padLen <= 8)
+ padLen += 64;
+ pad[0] = 0x80;
+ NdisZeroMemory(pad+1, padLen-7);
+ bitCount[0] = (context->count[0] << 3) | (context->count[1] >> 29);
+ bitCount[1] = context->count[1] << 3;
+ ByteReverse ((ULONG*)(pad+padLen-8), bitCount, 2);
+
+ /* Digest padding */
+ A_SHAUpdateCommon (context, pad, padLen, Transform);
+
+ /* Store digest */
+ ByteReverse ((ULONG*)digest, context->state, 5);
+
+ /* Restart the context */
+ A_SHAInitCommon (context);
+}
+
+void A_SHAInit (A_SHA_CTX *context)
+{
+ A_SHAInitCommon (&context->commonContext);
+}
+
+void A_SHAUpdate (context, partIn, partInLen)
+A_SHA_CTX *context;
+unsigned char *partIn;
+unsigned int partInLen;
+{
+ A_SHAUpdateCommon (&context->commonContext, partIn, partInLen, SHATransform);
+}
+
+void A_SHAFinal (context, digest)
+A_SHA_CTX *context;
+unsigned char digest[A_SHA_DIGEST_LEN];
+{
+ A_SHAFinalCommon (&context->commonContext, digest, SHATransform);
+}
+
+void SHATransform (state, block)
+ULONG state[5];
+unsigned char block[64];
+{
+ ULONG a = state[0], b = state[1], c = state[2], d = state[3],
+ e = state[4], x[80];
+
+ ByteReverse (x, (ULONG*)block, 16);
+ SHAExpand (x);
+
+ /* Round 1 */
+ FF (a, b, c, d, e, x[ 0]);
+ FF (e, a, b, c, d, x[ 1]);
+ FF (d, e, a, b, c, x[ 2]);
+ FF (c, d, e, a, b, x[ 3]);
+ FF (b, c, d, e, a, x[ 4]);
+ FF (a, b, c, d, e, x[ 5]);
+ FF (e, a, b, c, d, x[ 6]);
+ FF (d, e, a, b, c, x[ 7]);
+ FF (c, d, e, a, b, x[ 8]);
+ FF (b, c, d, e, a, x[ 9]);
+ FF (a, b, c, d, e, x[10]);
+ FF (e, a, b, c, d, x[11]);
+ FF (d, e, a, b, c, x[12]);
+ FF (c, d, e, a, b, x[13]);
+ FF (b, c, d, e, a, x[14]);
+ FF (a, b, c, d, e, x[15]);
+ FF (e, a, b, c, d, x[16]);
+ FF (d, e, a, b, c, x[17]);
+ FF (c, d, e, a, b, x[18]);
+ FF (b, c, d, e, a, x[19]);
+
+ /* Round 2 */
+ GG (a, b, c, d, e, x[20]);
+ GG (e, a, b, c, d, x[21]);
+ GG (d, e, a, b, c, x[22]);
+ GG (c, d, e, a, b, x[23]);
+ GG (b, c, d, e, a, x[24]);
+ GG (a, b, c, d, e, x[25]);
+ GG (e, a, b, c, d, x[26]);
+ GG (d, e, a, b, c, x[27]);
+ GG (c, d, e, a, b, x[28]);
+ GG (b, c, d, e, a, x[29]);
+ GG (a, b, c, d, e, x[30]);
+ GG (e, a, b, c, d, x[31]);
+ GG (d, e, a, b, c, x[32]);
+ GG (c, d, e, a, b, x[33]);
+ GG (b, c, d, e, a, x[34]);
+ GG (a, b, c, d, e, x[35]);
+ GG (e, a, b, c, d, x[36]);
+ GG (d, e, a, b, c, x[37]);
+ GG (c, d, e, a, b, x[38]);
+ GG (b, c, d, e, a, x[39]);
+
+ /* Round 3 */
+ HH (a, b, c, d, e, x[40]);
+ HH (e, a, b, c, d, x[41]);
+ HH (d, e, a, b, c, x[42]);
+ HH (c, d, e, a, b, x[43]);
+ HH (b, c, d, e, a, x[44]);
+ HH (a, b, c, d, e, x[45]);
+ HH (e, a, b, c, d, x[46]);
+ HH (d, e, a, b, c, x[47]);
+ HH (c, d, e, a, b, x[48]);
+ HH (b, c, d, e, a, x[49]);
+ HH (a, b, c, d, e, x[50]);
+ HH (e, a, b, c, d, x[51]);
+ HH (d, e, a, b, c, x[52]);
+ HH (c, d, e, a, b, x[53]);
+ HH (b, c, d, e, a, x[54]);
+ HH (a, b, c, d, e, x[55]);
+ HH (e, a, b, c, d, x[56]);
+ HH (d, e, a, b, c, x[57]);
+ HH (c, d, e, a, b, x[58]);
+ HH (b, c, d, e, a, x[59]);
+
+ /* Round 4 */
+ II (a, b, c, d, e, x[60]);
+ II (e, a, b, c, d, x[61]);
+ II (d, e, a, b, c, x[62]);
+ II (c, d, e, a, b, x[63]);
+ II (b, c, d, e, a, x[64]);
+ II (a, b, c, d, e, x[65]);
+ II (e, a, b, c, d, x[66]);
+ II (d, e, a, b, c, x[67]);
+ II (c, d, e, a, b, x[68]);
+ II (b, c, d, e, a, x[69]);
+ II (a, b, c, d, e, x[70]);
+ II (e, a, b, c, d, x[71]);
+ II (d, e, a, b, c, x[72]);
+ II (c, d, e, a, b, x[73]);
+ II (b, c, d, e, a, x[74]);
+ II (a, b, c, d, e, x[75]);
+ II (e, a, b, c, d, x[76]);
+ II (d, e, a, b, c, x[77]);
+ II (c, d, e, a, b, x[78]);
+ II (b, c, d, e, a, x[79]);
+
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+ state[4] += e;
+
+ /* Zeroize potentially sensitive information.
+ */
+ NdisZeroMemory((void *)x, sizeof (x));
+}
+
+/* Expands x[0..15] into x[16..79], according to the recurrence
+ x[i] = x[i-3] ^ x[i-8] ^ x[i-14] ^ x[i-16].
+ */
+void SHAExpand (x)
+ULONG x[80];
+{
+ unsigned int i;
+ ULONG tmp;
+
+ for (i = 16; i < 80; i++)
+ {
+ tmp = x[i-3] ^ x[i-8] ^ x[i-14] ^ x[i-16];
+ x[i] = (tmp << 1) | (tmp >> 31);
+ }
+}
+
+VOID
+ByteReverse(
+ ULONG *Out,
+ ULONG *In,
+ ULONG Count
+ )
+{
+ ULONG i;
+ ULONG Value;
+
+ for (i = 0; i < Count; i++) {
+ Value = (ULONG)(In[i] << 16) | (In[i] >> 16);
+ Out[i] = ((Value & 0xFF00FF00L) >> 8) | ((Value & 0x00FF00FFL) << 8);
+ }
+}
+
diff --git a/private/ntos/ndis/ndiswan/compress.h b/private/ntos/ndis/ndiswan/compress.h
new file mode 100644
index 000000000..a5bd31c29
--- /dev/null
+++ b/private/ntos/ndis/ndiswan/compress.h
@@ -0,0 +1,187 @@
+//************************************************************************
+// Microsoft Corporation
+// Copyright(c) Microsoft Corp., 1994
+//
+//
+// Revision history:
+// 5/5/94 Created gurdeep
+//
+// This file uses 4 space tabs
+//************************************************************************
+
+#ifdef COMP_12K
+#define HISTORY_SIZE 16000
+#else
+#define HISTORY_SIZE (8192U) // Maximum back-pointer value, also used
+#endif
+
+#define HISTORY_MAX (HISTORY_SIZE -1) // Maximum back-pointer value, also used
+
+#define HASH_TABLE_SIZE 4096
+
+#define MAX_BACK_PTR 8511
+
+#define MAX_COMPRESSFRAME_SIZE 1600
+
+struct SendContext {
+
+ UCHAR History [HISTORY_SIZE+1] ;
+
+ int CurrentIndex ; // how far into the history buffer we are
+
+ PUCHAR ValidHistory ; // how much of history is valid
+
+ UCHAR CompressBuffer[MAX_COMPRESSFRAME_SIZE] ;
+
+ USHORT HashTable[HASH_TABLE_SIZE];
+
+} ;
+
+typedef struct SendContext SendContext ;
+
+
+struct RecvContext {
+
+ UCHAR History [HISTORY_SIZE+1] ;
+
+#if DBG
+
+#define DEBUG_FENCE_VALUE 0xABABABAB
+ ULONG DebugFence;
+
+#endif
+
+ UCHAR *CurrentPtr ; // how far into the history buffer we are
+} ;
+
+typedef struct RecvContext RecvContext ;
+
+
+// Prototypes
+//
+UCHAR
+compress (
+ UCHAR *CurrentBuffer,
+ UCHAR *CompOutBuffer,
+ ULONG *CurrentLength,
+ SendContext *context);
+
+//UCHAR
+//compress (
+// UCHAR *CurrentBuffer,
+// ULONG *CurrentLength,
+// SendContext *context);
+
+int
+decompress (
+ UCHAR *inbuf,
+ int inlen,
+ int start,
+ UCHAR **output,
+ int *outlen,
+ RecvContext *context) ;
+
+void getcontextsizes (long *, long *) ;
+
+void initsendcontext (SendContext *) ;
+
+void initrecvcontext (RecvContext *) ;
+
+NDIS_STATUS
+InitSHAContext(
+ PENCRYPTION_INFO EncryptInfo
+ );
+
+VOID
+GetStartKeyFromSHA(
+ PENCRYPTION_INFO EncryptInfo,
+ PUCHAR Challenge
+ );
+
+VOID
+GetNewKeyFromSHA(
+ PENCRYPTION_INFO EncryptInfo
+ );
+
+
+//
+// Other defines
+//
+
+#define COMPRESSION_PADDING 4
+
+#define PACKET_FLUSHED 0x80
+#define PACKET_AT_FRONT 0x40
+#define PACKET_COMPRESSED 0x20
+#define PACKET_ENCRYPTED 0x10
+
+
+/* Copyright (C) RSA Data Security, Inc. created 1993. This is an
+ unpublished work protected as such under copyright law. This work
+ contains proprietary, confidential, and trade secret information of
+ RSA Data Security, Inc. Use, disclosure or reproduction without the
+ express written authorization of RSA Data Security, Inc. is
+ prohibited.
+ */
+
+#define A_SHA_DIGEST_LEN 20
+
+typedef struct {
+ ULONG state[5]; /* state (ABCDE) */
+ ULONG count[2]; /* number of UCHARs, msb first */
+ unsigned char buffer[64]; /* input buffer */
+} A_SHA_COMM_CTX;
+
+typedef void (A_SHA_TRANSFORM) (ULONG [5], unsigned char [64]);
+
+void A_SHAInitCommon (A_SHA_COMM_CTX *);
+void A_SHAUpdateCommon(A_SHA_COMM_CTX *, UCHAR *, ULONG, A_SHA_TRANSFORM *);
+void A_SHAFinalCommon(A_SHA_COMM_CTX *, UCHAR[A_SHA_DIGEST_LEN],
+ A_SHA_TRANSFORM *);
+
+VOID ByteReverse(ULONG* Out, ULONG* In, ULONG Count);
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+ ULONG FinishFlag;
+ UCHAR HashVal[A_SHA_DIGEST_LEN];
+ A_SHA_COMM_CTX commonContext;
+} A_SHA_CTX;
+
+void A_SHAInit(A_SHA_CTX *);
+void A_SHAUpdate(A_SHA_CTX *, unsigned char *, unsigned int);
+void A_SHAFinal(A_SHA_CTX *, unsigned char [A_SHA_DIGEST_LEN]);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+/* F, G, H and I are basic SHA functions.
+ */
+#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
+#define G(x, y, z) ((x) ^ (y) ^ (z))
+#define H(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
+#define I(x, y, z) ((x) ^ (y) ^ (z))
+
+/* ROTATE_LEFT rotates x left n bits.
+ */
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
+
+/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
+ */
+#define ROUND(a, b, c, d, e, x, F, k) { \
+ (e) += ROTATE_LEFT ((a), 5) + F ((b), (c), (d)) + (x) + k; \
+ (b) = ROTATE_LEFT ((b), 30); \
+ }
+#define FF(a, b, c, d, e, x) ROUND (a, b, c, d, e, x, F, 0x5a827999);
+#define GG(a, b, c, d, e, x) ROUND (a, b, c, d, e, x, G, 0x6ed9eba1);
+#define HH(a, b, c, d, e, x) ROUND (a, b, c, d, e, x, H, 0x8f1bbcdc);
+#define II(a, b, c, d, e, x) ROUND (a, b, c, d, e, x, I, 0xca62c1d6);
+
+void SHATransform(ULONG [5], unsigned char [64]);
+void SHAExpand(ULONG [80]);
+
diff --git a/private/ntos/ndis/ndiswan/dirs b/private/ntos/ndis/ndiswan/dirs
new file mode 100644
index 000000000..8a1ff70d8
--- /dev/null
+++ b/private/ntos/ndis/ndiswan/dirs
@@ -0,0 +1,26 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Steve Wood (stevewo) 17-Apr-1990
+
+NOTE: Commented description of this file is in \nt\bak\bin\dirs.tpl
+
+!ENDIF
+
+DIRS=domestic \
+ export
+
+OPTIONAL_DIRS=kdexts
diff --git a/private/ntos/ndis/ndiswan/export/makefile b/private/ntos/ndis/ndiswan/export/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/ndis/ndiswan/export/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/ndis/ndiswan/export/sources b/private/ntos/ndis/ndiswan/export/sources
new file mode 100644
index 000000000..2bc2f0dec
--- /dev/null
+++ b/private/ntos/ndis/ndiswan/export/sources
@@ -0,0 +1,59 @@
+!IF 0
+
+Copyright (c) 1989-1993 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1990
+
+NOTE: Commented description of this file is in \nt\bak\bin\sources.tpl
+
+!ENDIF
+
+MAJORCOMP=ntos
+MINORCOMP=ndis
+
+TARGETNAME=ndiswan
+TARGETPATH=$(BASEDIR)\public\sdk\lib
+TARGETTYPE=DRIVER
+
+TARGETLIBS=$(BASEDIR)\public\sdk\lib\*\ndis.lib \
+ $(BASEDIR)\public\sdk\lib\*\ndistapi.lib \
+ ..\..\..\..\lsa\crypt\engine\obj\*\rc4c.obj
+
+INCLUDES=..\..\inc;..\..\..\inc;..\..\..\..\inc;..\..\..\..\lsa\crypt\engine;..\..\..\tdi\nbf;..\..\..\tdi\isnp\ipx
+
+#C_DEFINES=-DNT -DNDIS_MINIPORT_DRIVER -DBINARY_COMPATIBLE=0 -DNDIS_WRAPPER
+C_DEFINES=-DNT -DNDIS_WRAPPER
+
+SOURCES=..\ndiswan.c \
+ ..\send.c \
+ ..\compress.c \
+ ..\receive.c \
+ ..\io.c \
+ ..\miniport.c \
+ ..\protocol.c \
+ ..\util.c \
+ ..\request.c \
+ ..\memory.c \
+ ..\indicate.c \
+ ..\vjslip.c \
+ ..\tapi.c \
+ ..\ccp.c \
+ ..\loopback.c \
+ ..\ndiswan.rc
+
+MSC_WARNING_LEVEL=/W3 /WX
+
diff --git a/private/ntos/ndis/ndiswan/global.h b/private/ntos/ndis/ndiswan/global.h
new file mode 100644
index 000000000..4f60ef906
--- /dev/null
+++ b/private/ntos/ndis/ndiswan/global.h
@@ -0,0 +1,52 @@
+/*++
+
+Copyright (c) 1990-1995 Microsoft Corporation
+
+Module Name:
+
+ Global.h
+
+Abstract:
+
+ This file contains global structures for the NdisWan driver.
+
+Author:
+
+ Tony Bell (TonyBe) June 06, 1995
+
+Environment:
+
+ Kernel Mode
+
+Revision History:
+
+ TonyBe 06/06/95 Created
+
+--*/
+
+#ifndef _NDISWAN_GLOBAL_
+#define _NDISWAN_GLOBAL_
+
+extern NDISWANCB NdisWanCB; // Global ndiswan control block
+
+extern WAN_GLOBAL_LIST ThresholdEventQueue; // Queue to hold threshold events
+
+extern WAN_GLOBAL_LIST RecvPacketQueue; // Queue to hold ppp receive packets
+
+extern WAN_GLOBAL_LIST FreeBundleCBList; // List of free BundleCB's
+
+extern WAN_GLOBAL_LIST FreeProtocolCBList; // List of free ProtocolCB's
+
+extern WAN_GLOBAL_LIST AdapterCBList; // List of NdisWan AdapterCB's
+
+extern WAN_GLOBAL_LIST WanAdapterCBList; // List of WAN Miniport structures
+
+extern WAN_GLOBAL_LIST GlobalRecvDescPool; // Global pool of free recvdesc's
+
+extern PCONNECTION_TABLE ConnectionTable; // Pointer to connection table
+
+extern PPPP_PROTOCOL_TABLE PPP_ProtocolTable; // Pointer to the PPP/Protocol value lookup table
+
+extern NDIS_PHYSICAL_ADDRESS HighestAcceptableAddress;
+
+#endif // _NDISWAN_GLOBAL_
diff --git a/private/ntos/ndis/ndiswan/indicate.c b/private/ntos/ndis/ndiswan/indicate.c
new file mode 100644
index 000000000..40e0d61ae
--- /dev/null
+++ b/private/ntos/ndis/ndiswan/indicate.c
@@ -0,0 +1,611 @@
+/*++
+
+Copyright (c) 1990-1995 Microsoft Corporation
+
+Module Name:
+
+ Indicate.c
+
+Abstract:
+
+ This file contains procedures to handle indications from the
+ WAN Miniport drivers.
+
+
+Author:
+
+ Tony Bell (TonyBe) June 06, 1995
+
+Environment:
+
+ Kernel Mode
+
+Revision History:
+
+ TonyBe 06/06/95 Created
+
+--*/
+
+#include "wan.h"
+
+
+VOID
+NdisWanLineUpIndication(
+ PWAN_ADAPTERCB WanAdapterCB,
+ PUCHAR Buffer,
+ ULONG BufferSize
+ )
+/*++
+
+Routine Name:
+
+ NdisWanLineupIndication
+
+Routine Description:
+
+ This routine is called when a WAN Miniport driver has a new connetion
+ become active or when the status of an active connection changes. If
+ this is a new connection the routine creates a LinkCB, and a BundleCB
+ for the new connection. If this is for an already active connetion the
+ connection info is updated.
+
+Arguments:
+
+Return Values:
+
+ None
+
+--*/
+{
+ PLINKCB LinkCB;
+ PBUNDLECB BundleCB;
+ PPROTOCOLCB ProtocolCB;
+ NDIS_STATUS Status;
+ PNDIS_MAC_LINE_UP LineUpInfo = (PNDIS_MAC_LINE_UP)Buffer;
+ PNDIS_MAC_LINE_UP LinkLineUpInfo;
+ BOOLEAN EmptyList;
+
+ if (BufferSize >= sizeof(NDIS_MAC_LINE_UP)) {
+
+ //
+ // Is this for a new connetion?
+ //
+ if (LineUpInfo->NdisLinkContext == NULL) {
+
+ //
+ // This is a new connection!
+ //
+
+ //
+ // Get a linkcb
+ //
+ NdisWanGetLinkCB(&LinkCB,
+ WanAdapterCB,
+ LineUpInfo->SendWindow);
+
+ if (LinkCB == NULL) {
+
+ //
+ // Error getting LinkCB!
+ //
+
+ return;
+
+ }
+
+ LinkCB->NdisLinkHandle = LineUpInfo->NdisLinkHandle;
+
+ //
+ // Get a bundlecb
+ //
+ NdisWanGetBundleCB(&BundleCB);
+
+ if (BundleCB == NULL) {
+
+ //
+ // Error getting BundleCB!
+ //
+
+ NdisWanReturnLinkCB(LinkCB);
+
+ return;
+ }
+
+ //
+ // Copy LineUpInfo to Link LineUpInfo
+ //
+ NdisMoveMemory((PUCHAR)&LinkCB->LineUpInfo,
+ (PUCHAR)LineUpInfo,
+ sizeof(NDIS_MAC_LINE_UP));
+
+ //
+ // Add LinkCB to BundleCB
+ //
+ AddLinkToBundle(BundleCB, LinkCB);
+
+ //
+ // Place BundleCB in active connection table
+ //
+ InsertBundleInConnectionTable(BundleCB);
+
+ //
+ // Place LinkCB in active connection table
+ //
+ InsertLinkInConnectionTable(LinkCB);
+
+ LineUpInfo->NdisLinkContext = (NDIS_HANDLE)LinkCB->hLinkHandle;
+
+
+ } else {
+
+ //
+ // This is an already existing connetion
+ //
+ LINKCB_FROM_LINKH(LinkCB, LineUpInfo->NdisLinkContext);
+
+ if (LinkCB == NULL) {
+#if DBG
+ DbgPrint("NDISWAN.SYS: Invalid LinkContext (0x%8.8x) in LineUp!",
+ LineUpInfo->NdisLinkContext);
+#endif
+ return;
+ }
+
+ BundleCB = BUNDLECB_FROM_LINKCB(LinkCB);
+
+ if (BundleCB == NULL) {
+#if DBG
+ DbgPrint("NDISWAN.SYS: Invalid BundleCB in LineUp, BundleCB: 0x%8.8x, LinkCB: 0x%8.8x\n",
+ LinkCB, BundleCB);
+#endif
+ return;
+ }
+
+ NdisAcquireSpinLock(&BundleCB->Lock);
+
+ LinkLineUpInfo = &LinkCB->LineUpInfo;
+
+ LinkLineUpInfo->LinkSpeed = LineUpInfo->LinkSpeed;
+ LinkLineUpInfo->Quality = LineUpInfo->Quality;
+ LinkLineUpInfo->SendWindow = LineUpInfo->SendWindow;
+
+ //
+ // Update BundleCB info
+ //
+ UpdateBundleInfo(BundleCB);
+
+ NdisReleaseSpinLock(&BundleCB->Lock);
+ }
+ }
+}
+
+
+VOID
+NdisWanLineDownIndication(
+ PWAN_ADAPTERCB WanAdapterCB,
+ PUCHAR Buffer,
+ ULONG BufferSize
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ PNDIS_MAC_LINE_DOWN LineDownInfo = (PNDIS_MAC_LINE_DOWN)Buffer;
+ PLINKCB LinkCB;
+ PBUNDLECB BundleCB;
+ PPROTOCOLCB ProtocolCB;
+ BOOLEAN FreeBundle = FALSE;
+ BOOLEAN FreeLink = FALSE;
+
+ LINKCB_FROM_LINKH(LinkCB, (ULONG)LineDownInfo->NdisLinkContext);
+
+ if (LinkCB == NULL) {
+ return;
+ }
+
+ BundleCB = LinkCB->BundleCB;
+
+ NdisAcquireSpinLock(&BundleCB->Lock);
+
+ //
+ // Link is now going down
+ //
+ LinkCB->State = LINK_GOING_DOWN;
+
+ //
+ // If there are not any frames pending on this
+ // link we will go ahead and free it's resources.
+ // If there are frames pending the resources will
+ // be freed in the sendcomplete routine.
+ //
+ if (LinkCB->OutstandingFrames == 0) {
+
+ //
+ // Mark this link as being down
+ //
+ LinkCB->State = LINK_DOWN;
+ FreeLink = TRUE;
+
+ //
+ // Remove the link from the bundle
+ //
+ RemoveLinkFromBundle(BundleCB, LinkCB);
+
+ }
+
+ //
+ // If this bundle's link count has gone to
+ // zero and it is not been routed yet no
+ // user-mode component will be freeing the
+ // resources so we may need to free the
+ // resources.
+ //
+ if (BundleCB->ulLinkCBCount == 0) {
+
+ BundleCB->State = BUNDLE_GOING_DOWN;
+
+ //
+ // If there are not any frames pending on this
+ // bundle so we need to free it's resources now.
+ // If there are frames pending the resources will
+ // be freed in the sendcomplete routine.
+ //
+ if ((BundleCB->OutstandingFrames == 0) &&
+ !(BundleCB->Flags & BUNDLE_ROUTED)) {
+
+ BundleCB->State = BUNDLE_DOWN;
+
+ FreeBundle = TRUE;
+ }
+ }
+
+ NdisReleaseSpinLock(&BundleCB->Lock);
+
+ if (FreeLink) {
+ //
+ // Remove this link from the connection table
+ //
+ RemoveLinkFromConnectionTable(LinkCB);
+ NdisWanReturnLinkCB(LinkCB);
+ }
+
+ if (FreeBundle) {
+ //
+ // Remove this bundle from the connection table
+ //
+ RemoveBundleFromConnectionTable(BundleCB);
+ NdisWanReturnBundleCB(BundleCB);
+ }
+
+}
+
+
+VOID
+NdisWanFragmentIndication(
+ PWAN_ADAPTERCB WanAdapterCB,
+ PUCHAR Buffer,
+ ULONG BufferSize
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ PNDIS_MAC_FRAGMENT FragmentInfo = (PNDIS_MAC_FRAGMENT)Buffer;
+ PLINKCB LinkCB;
+ PBUNDLECB BundleCB;
+
+ LINKCB_FROM_LINKH(LinkCB, (ULONG)FragmentInfo->NdisLinkContext);
+
+ if (LinkCB == NULL) {
+ return;
+ }
+
+ BundleCB = LinkCB->BundleCB;
+
+ if (BundleCB == NULL) {
+ return;
+ }
+
+ NdisAcquireSpinLock(&BundleCB->Lock);
+
+ if (FragmentInfo->Errors & WAN_ERROR_CRC) {
+ LinkCB->LinkStats.CRCErrors++;
+ BundleCB->BundleStats.CRCErrors++;
+ }
+
+ if (FragmentInfo->Errors & WAN_ERROR_FRAMING) {
+ LinkCB->LinkStats.FramingErrors++;
+ BundleCB->BundleStats.FramingErrors++;
+ }
+
+ if (FragmentInfo->Errors & WAN_ERROR_HARDWAREOVERRUN) {
+ LinkCB->LinkStats.SerialOverrunErrors++;
+ BundleCB->BundleStats.SerialOverrunErrors++;
+ }
+
+ if (FragmentInfo->Errors & WAN_ERROR_BUFFEROVERRUN) {
+ LinkCB->LinkStats.BufferOverrunErrors++;
+ BundleCB->BundleStats.BufferOverrunErrors++;
+ }
+
+ if (FragmentInfo->Errors & WAN_ERROR_TIMEOUT) {
+ LinkCB->LinkStats.TimeoutErrors++;
+ BundleCB->BundleStats.TimeoutErrors++;
+ }
+
+ if (FragmentInfo->Errors & WAN_ERROR_ALIGNMENT) {
+ LinkCB->LinkStats.AlignmentErrors++;
+ BundleCB->BundleStats.AlignmentErrors++;
+ }
+
+ NdisReleaseSpinLock(&BundleCB->Lock);
+
+}
+
+VOID
+UpdateBundleInfo(
+ PBUNDLECB BundleCB
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+ Expects the BundleCB->Lock to be held!
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ PLINKCB LinkCB;
+ ULONG SlowestLink;
+ PPROTOCOLCB ProtocolCB, IoProtocolCB;
+#ifdef BANDWIDTH_ON_DEMAND
+ ULONG SecondsInSamplePeriod;
+ ULONG BytesPerSecond;
+ ULONG BytesInSamplePeriod;
+#endif // end of BANDWIDTH_ON_DEMAND
+
+ //
+ // If there are any links attached to this bundlecb we will
+ // update the bundlecb's info
+ //
+ if (BundleCB->ulLinkCBCount != 0) {
+ PBUNDLE_LINE_UP BundleLineUpInfo = &BundleCB->LineUpInfo;
+
+ SlowestLink =
+ BundleLineUpInfo->BundleSpeed = 0;
+ BundleLineUpInfo->usSendWindow = 0;
+ BundleLineUpInfo->Quality = NdisWanReliable;
+
+ //
+ // Walk the LinkCBList and update the bundle's info
+ //
+ for (LinkCB = (PLINKCB)BundleCB->LinkCBList.Flink;
+ (PVOID)LinkCB != (PVOID)&BundleCB->LinkCBList;
+ LinkCB = (PLINKCB)LinkCB->Linkage.Flink) {
+
+ PWAN_ADAPTERCB WanAdapterCB = LinkCB->WanAdapterCB;
+ PNDIS_MAC_LINE_UP LinkLineUpInfo = &LinkCB->LineUpInfo;
+
+ //
+ // Bundle link speed is total of all links. Keep track
+ // of slowest link for multilink recv desc's time to live.
+ //
+ BundleLineUpInfo->BundleSpeed += LinkLineUpInfo->LinkSpeed;
+ if ((LinkLineUpInfo->LinkSpeed < SlowestLink) || (SlowestLink == 0)) {
+ SlowestLink = LinkLineUpInfo->LinkSpeed;
+ }
+
+ //
+ // Bundle send windows is the total of all links
+ //
+ BundleLineUpInfo->usSendWindow += LinkLineUpInfo->SendWindow;
+
+ //
+ // Bundle line quality is the worst of all links
+ //
+ if (BundleLineUpInfo->Quality < LinkLineUpInfo->Quality) {
+ BundleLineUpInfo->Quality = LinkLineUpInfo->Quality;
+ }
+
+ }
+
+#if 0
+ //
+ // Update the time to live for multilink recv desc's. This is in ms and
+ // is the time it would take to receive a complete frame of size MRRU
+ // across the slowest link in the bundle. Value must be a multiple of
+ // 100ms with a minimum value of 1sec. If the slowest link in the bundle is
+ // slower than a 28.8K modem we will increase the timeout value by 2
+ //
+ if (SlowestLink == 0) {
+ SlowestLink = 288;
+ }
+
+ BundleCB->TimeToLive =
+ (BundleCB->FramingInfo.MaxRRecvFrameSize * 1000) /
+ ((SlowestLink * 100) / 8);
+
+ if (SlowestLink < 64) {
+ BundleCB->TimeToLive *= 2;
+ }
+
+ BundleCB->TimeToLive |= 0x3E8;
+ BundleCB->TimeToLive /= 0x64;
+ BundleCB->TimeToLive *= 0x64;
+#endif
+
+ //
+ // Now calculate the % bandwidth that each links contributes to the
+ // bundle.
+ //
+ BundleCB->NextLinkToXmit = (PLINKCB)BundleCB->LinkCBList.Flink;
+
+ for (LinkCB = (PLINKCB)BundleCB->LinkCBList.Flink;
+ (PVOID)LinkCB != (PVOID)&BundleCB->LinkCBList;
+ LinkCB = (PLINKCB)LinkCB->Linkage.Flink) {
+
+ if (LinkCB->LineUpInfo.LinkSpeed != 0) {
+ ULONG n, d, temp;
+
+ d = BundleCB->LineUpInfo.BundleSpeed;
+ n = LinkCB->LineUpInfo.LinkSpeed * 100;
+
+ LinkCB->ulBandwidth = (temp = (n / d)) ? temp : 1;
+ } else {
+ LinkCB->ulBandwidth = 1;
+ }
+
+ if (LinkCB->ulBandwidth > ((PLINKCB)(BundleCB->NextLinkToXmit))->ulBandwidth) {
+ BundleCB->NextLinkToXmit = LinkCB;
+ }
+ }
+
+
+#ifdef BANDWIDTH_ON_DEMAND
+
+ //
+ // Update the BandwidthOnDemand information
+ //
+ SecondsInSamplePeriod = BundleCB->UpperBonDInfo.ulSecondsInSamplePeriod;
+
+ BytesPerSecond = BundleCB->LineUpInfo.BundleSpeed * 100 / 8;
+
+ BytesInSamplePeriod = BytesPerSecond * SecondsInSamplePeriod;
+
+ BundleCB->UpperBonDInfo.ulBytesThreshold = BytesInSamplePeriod *
+ BundleCB->UpperBonDInfo.usPercentBandwidth / 100;
+
+ SecondsInSamplePeriod = BundleCB->LowerBonDInfo.ulSecondsInSamplePeriod;
+
+ BytesPerSecond = BundleCB->LineUpInfo.BundleSpeed * 100 / 8;
+
+ BytesInSamplePeriod = BytesPerSecond * SecondsInSamplePeriod;
+
+ BundleCB->LowerBonDInfo.ulBytesThreshold = BytesInSamplePeriod *
+ BundleCB->LowerBonDInfo.usPercentBandwidth / 100;
+
+#endif // end of BANDWIDTH_ON_DEMAND
+
+ //
+ // We need to do a new lineup to all routed protocols skipping
+ // the IoProtocolCB!
+ //
+ IoProtocolCB = (PPROTOCOLCB)BundleCB->ProtocolCBList.Flink;
+
+ for (ProtocolCB = (PPROTOCOLCB)IoProtocolCB->Linkage.Flink;
+ (PVOID)ProtocolCB != (PVOID)&BundleCB->ProtocolCBList;
+ ProtocolCB = (PPROTOCOLCB)ProtocolCB->Linkage.Flink) {
+
+#ifdef BANDWIDTH_ON_DEMAND
+
+ ProtocolCB->ulByteQuota =
+ (BytesPerSecond * ProtocolCB->usPriority) / 100;
+
+#endif // end of BANDWIDTH_ON_DEMAND
+
+ NdisReleaseSpinLock(&BundleCB->Lock);
+
+ DoLineUpToProtocol(ProtocolCB);
+
+ NdisAcquireSpinLock(&BundleCB->Lock);
+ }
+
+ }
+}
+
+
+VOID
+AddLinkToBundle(
+ IN PBUNDLECB BundleCB,
+ IN PLINKCB LinkCB
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ NdisAcquireSpinLock(&(BundleCB->Lock));
+
+ InsertTailList(&(BundleCB->LinkCBList), &(LinkCB->Linkage));
+
+ BundleCB->ulLinkCBCount++;
+
+ BundleCB->SendingLinks++;
+
+ LinkCB->BundleCB = BundleCB;
+
+ LinkCB->LastRecvSeqNumber = BundleCB->MinReceivedSeqNumber;
+
+ //
+ // Update BundleCB Info
+ //
+ UpdateBundleInfo(BundleCB);
+
+ NdisReleaseSpinLock(&(BundleCB->Lock));
+}
+
+VOID
+RemoveLinkFromBundle(
+ IN PBUNDLECB BundleCB,
+ IN PLINKCB LinkCB
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+ Expects the BundleCB->Lock to be held!
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+
+ //
+ // Remove link from the bundle
+ //
+ RemoveEntryList(&LinkCB->Linkage);
+
+ LinkCB->BundleCB = NULL;
+
+ BundleCB->ulLinkCBCount--;
+
+ BundleCB->SendingLinks--;
+
+ //
+ // Update BundleCB LineUp Info
+ //
+ UpdateBundleInfo(BundleCB);
+
+}
diff --git a/private/ntos/ndis/ndiswan/io.c b/private/ntos/ndis/ndiswan/io.c
new file mode 100644
index 000000000..ec757be38
--- /dev/null
+++ b/private/ntos/ndis/ndiswan/io.c
@@ -0,0 +1,4608 @@
+/*++
+
+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;
+}
+
diff --git a/private/ntos/ndis/ndiswan/kdexts/api.c b/private/ntos/ndis/ndiswan/kdexts/api.c
new file mode 100644
index 000000000..d46296696
--- /dev/null
+++ b/private/ntos/ndis/ndiswan/kdexts/api.c
@@ -0,0 +1,385 @@
+#include <wanhelp.h>
+
+DECLARE_API(ndiswancb)
+{
+ DWORD Address, BytesRead;
+ NDISWANCB NdisWanCB;
+
+ Address = GetExpression("ndiswan!ndiswancb");
+
+ if (!ReadMemory(Address, &NdisWanCB, sizeof(NDISWANCB), &BytesRead)) {
+ return;
+ }
+
+ if (BytesRead >= sizeof(NDISWANCB)) {
+
+ DisplayNdisWanCB(Address, &NdisWanCB);
+
+ } else {
+ dprintf("Only read %d bytes, expected %d bytes\n", BytesRead, sizeof(NdisWanCB));
+ }
+
+ return;
+}
+
+DECLARE_API(enumwanadaptercb)
+{
+ DWORD Address, BytesRead;
+ WAN_GLOBAL_LIST AdapterList;
+ PWAN_GLOBAL_LIST Address1;
+
+ Address = GetExpression("ndiswan!wanadaptercblist");
+ Address1 = (PWAN_GLOBAL_LIST)Address;
+
+ if (!ReadMemory(Address, &AdapterList, sizeof(WAN_GLOBAL_LIST), &BytesRead)) {
+ return;
+ }
+
+ if (BytesRead >= sizeof(WAN_GLOBAL_LIST)) {
+ dprintf("WanAdapterCBList: 0x%8.8x\n",Address);
+ dprintf(" Lock: 0x%8.8x Irql: 0x%8.8x\n",
+ AdapterList.Lock.SpinLock, AdapterList.Lock.OldIrql);
+ dprintf(" Count: %ld MaxCount: %ld\n",
+ AdapterList.ulCount, AdapterList.ulMaxCount);
+
+ Address = AdapterList.List.Flink;
+
+ while ((PVOID)Address != (PVOID)&Address1->List) {
+ WAN_ADAPTERCB WanAdapterCB;
+
+ if (ReadMemory(Address, &WanAdapterCB, sizeof(WAN_ADAPTERCB), &BytesRead)) {
+ DisplayWanAdapterCB(Address, &WanAdapterCB);
+ }
+
+ Address = (DWORD)WanAdapterCB.Linkage.Flink;
+ }
+
+ } else {
+
+ dprintf("Only read %d bytes, expected %d bytes\n", BytesRead, sizeof(WAN_GLOBAL_LIST));
+ }
+}
+
+DECLARE_API(wanadaptercb)
+{
+ DWORD Address, BytesRead;
+ WAN_ADAPTERCB WanAdapterCB;
+ PUCHAR s = (PSTR)args;
+ BOOLEAN Verbose = FALSE;
+
+ //
+ // Did they forget something...
+ //
+ if (0 == args[0])
+ {
+Usage:
+ dprintf("wanadapter <PWANADAPTERCB>\n");
+ return;
+ }
+
+ sscanf(args, "%lx", &Address);
+
+ if (!ReadMemory(Address, &WanAdapterCB, sizeof(WAN_ADAPTERCB), &BytesRead)) {
+ return;
+ }
+
+ if (BytesRead >= sizeof(WAN_ADAPTERCB)) {
+
+ DisplayWanAdapterCB(Address, &WanAdapterCB);
+
+ } else {
+ dprintf("Only read %d bytes, expected %d bytes\n", BytesRead, sizeof(WanAdapterCB));
+ }
+}
+
+DECLARE_API(enumadaptercb)
+{
+ DWORD Address, BytesRead;
+ WAN_GLOBAL_LIST AdapterList;
+ PWAN_GLOBAL_LIST Address1;
+
+
+ Address = GetExpression("ndiswan!adaptercblist");
+ Address1 = (PWAN_GLOBAL_LIST)Address;
+
+ if (!ReadMemory(Address, &AdapterList, sizeof(WAN_GLOBAL_LIST), &BytesRead)) {
+ return;
+ }
+
+ if (BytesRead >= sizeof(WAN_GLOBAL_LIST)) {
+
+ dprintf("AdapterCBList: 0x%8.8x\n",Address);
+ dprintf(" Lock: 0x%8.8x Irql: 0x%8.8x\n",
+ AdapterList.Lock.SpinLock, AdapterList.Lock.OldIrql);
+ dprintf(" Count: %ld MaxCount: %ld\n",
+ AdapterList.ulCount, AdapterList.ulMaxCount);
+
+ Address = AdapterList.List.Flink;
+
+ while ((PVOID)Address != (PVOID)&Address1->List) {
+ ADAPTERCB AdapterCB;
+
+ if (ReadMemory(Address, &AdapterCB, sizeof(ADAPTERCB), &BytesRead)) {
+ DisplayAdapterCB(Address, &AdapterCB);
+ }
+
+ Address = (DWORD)AdapterCB.Linkage.Flink;
+ }
+ } else {
+
+ dprintf("Only read %d bytes, expected %d bytes\n", BytesRead, sizeof(WAN_GLOBAL_LIST));
+ }
+}
+
+DECLARE_API(adaptercb)
+{
+ DWORD Address, BytesRead;
+ ADAPTERCB AdapterCB;
+ PUCHAR s = (PSTR)args;
+ BOOLEAN Verbose = FALSE;
+
+ //
+ // Did they forget something...
+ //
+ if (0 == args[0])
+ {
+Usage:
+ dprintf("adapter <PADAPTERCB>\n");
+ return;
+ }
+
+ sscanf(args, "%lx", &Address);
+
+ if (!ReadMemory(Address, &AdapterCB, sizeof(ADAPTERCB), &BytesRead)) {
+ return;
+ }
+
+ if (BytesRead >= sizeof(ADAPTERCB)) {
+
+ DisplayAdapterCB(Address, &AdapterCB);
+
+ } else {
+ dprintf("Only read %d bytes, expected %d bytes\n", BytesRead, sizeof(AdapterCB));
+ }
+}
+
+DECLARE_API(connectiontable)
+{
+ DWORD Address, Address1, BytesRead, i, j;
+ CONNECTION_TABLE ConnectionTable;
+
+ Address = GetExpression("ndiswan!connectiontable");
+
+ if (!ReadMemory(Address, &Address1, sizeof(DWORD), &BytesRead)) {
+ return;
+ }
+
+ if (!ReadMemory(Address1, &ConnectionTable, sizeof(CONNECTION_TABLE), &BytesRead)) {
+ return;
+ }
+
+ if (BytesRead >= sizeof(CONNECTION_TABLE)) {
+ DisplayConnectionTable(Address, &ConnectionTable);
+
+ for (i = 0, j = 0; j < ConnectionTable.ulNumActiveLinks; i++) {
+ LINKCB LinkCB;
+
+ //
+ // Get pointer to location in Linktable
+ //
+ Address = ConnectionTable.LinkArray + i;
+
+ if (!ReadMemory(Address, &Address1, sizeof(DWORD), &BytesRead)) {
+ continue;
+ }
+
+ if (Address1 != NULL) {
+
+ if (ReadMemory(Address1, &LinkCB, sizeof(LINKCB), &BytesRead)) {
+ DisplayLinkCB(Address1, &LinkCB);
+ j++;
+ }
+
+ }
+
+ }
+
+ for (i = 0, j = 0; j < ConnectionTable.ulNumActiveBundles; i++) {
+ BUNDLECB BundleCB;
+
+ //
+ // Get pointer to location in bundletable
+ //
+ Address = ConnectionTable.BundleArray + i;
+
+
+ if (!ReadMemory(Address, &Address1, sizeof(DWORD), &BytesRead)) {
+ continue;
+ }
+
+ if (Address1 != NULL) {
+
+ if (ReadMemory(Address1, &BundleCB, sizeof(BUNDLECB), &BytesRead)) {
+ DisplayBundleCB(Address1, &BundleCB);
+ j++;
+ }
+ }
+
+ }
+
+ } else {
+ dprintf("Only read %d bytes, expected %d bytes\n", BytesRead, sizeof(CONNECTION_TABLE));
+ }
+}
+
+DECLARE_API(bundlecb)
+{
+ DWORD Address, BytesRead;
+ BUNDLECB BundleCB;
+
+ //
+ // Did they forget something...
+ //
+ if (0 == args[0])
+ {
+Usage:
+ dprintf("bundlecb <PBUNDLECB>\n");
+ return;
+ }
+
+ sscanf(args, "%lx", &Address);
+
+ if (!ReadMemory(Address, &BundleCB, sizeof(BUNDLECB), &BytesRead)) {
+ return;
+ }
+
+ if (BytesRead >= sizeof(BUNDLECB)) {
+
+ DisplayBundleCB(Address, &BundleCB);
+
+ } else {
+ dprintf("Only read %d bytes, expected %d bytes\n", BytesRead, sizeof(BUNDLECB));
+ }
+}
+
+DECLARE_API(linkcb)
+{
+ DWORD Address, BytesRead;
+ LINKCB LinkCB;
+
+ //
+ // Did they forget something...
+ //
+ if (0 == args[0])
+ {
+Usage:
+ dprintf("linkcb <PLINKCB>\n");
+ return;
+ }
+
+ sscanf(args, "%lx", &Address);
+
+ if (!ReadMemory(Address, &LinkCB, sizeof(LINKCB), &BytesRead)) {
+ return;
+ }
+
+ if (BytesRead >= sizeof(LINKCB)) {
+
+ DisplayLinkCB(Address, &LinkCB);
+
+ } else {
+ dprintf("Only read %d bytes, expected %d bytes\n", BytesRead, sizeof(LINKCB));
+ }
+}
+
+DECLARE_API(protocolcb)
+{
+ DWORD Address, BytesRead;
+ PROTOCOLCB ProtocolCB;
+
+ //
+ // Did they forget something...
+ //
+ if (0 == args[0])
+ {
+Usage:
+ dprintf("protocolcb <PPROTOCOLCB>\n");
+ return;
+ }
+
+ sscanf(args, "%lx", &Address);
+
+ if (!ReadMemory(Address, &ProtocolCB, sizeof(PROTOCOLCB), &BytesRead)) {
+ return;
+ }
+
+ if (BytesRead >= sizeof(PROTOCOLCB)) {
+
+ DisplayProtocolCB(Address, &ProtocolCB);
+
+ } else {
+ dprintf("Only read %d bytes, expected %d bytes\n", BytesRead, sizeof(PROTOCOLCB));
+ }
+}
+
+DECLARE_API(wanpacket)
+{
+ DWORD Address, BytesRead;
+ NDIS_WAN_PACKET Packet;
+
+ //
+ // Did they forget something...
+ //
+ if (0 == args[0])
+ {
+Usage:
+ dprintf("wanpacket <PNDIS_WAN_PACKET>\n");
+ return;
+ }
+
+ sscanf(args, "%lx", &Address);
+
+ if (!ReadMemory(Address, &Packet, sizeof(NDIS_WAN_PACKET), &BytesRead)) {
+ return;
+ }
+
+ if (BytesRead >= sizeof(NDIS_WAN_PACKET)) {
+
+ DisplayWanPacket(Address, &Packet);
+
+ } else {
+ dprintf("Only read %d bytes, expected %d bytes\n", BytesRead, sizeof(NDIS_WAN_PACKET));
+ }
+}
+
+DECLARE_API(ndispacket)
+{
+ DWORD Address, BytesRead;
+ NDIS_PACKET Packet;
+
+ //
+ // Did they forget something...
+ //
+ if (0 == args[0])
+ {
+Usage:
+ dprintf("ndispacket <PNDIS_PACKET>\n");
+ return;
+ }
+
+ sscanf(args, "%lx", &Address);
+
+ if (!ReadMemory(Address, &Packet, sizeof(NDIS_PACKET), &BytesRead)) {
+ return;
+ }
+
+ if (BytesRead >= sizeof(NDIS_PACKET)) {
+
+ DisplayNdisPacket(Address, &Packet);
+
+ } else {
+ dprintf("Only read %d bytes, expected %d bytes\n", BytesRead, sizeof(NDIS_PACKET));
+ }
+}
+
+
diff --git a/private/ntos/ndis/ndiswan/kdexts/display.c b/private/ntos/ndis/ndiswan/kdexts/display.c
new file mode 100644
index 000000000..cf412c0e9
--- /dev/null
+++ b/private/ntos/ndis/ndiswan/kdexts/display.c
@@ -0,0 +1,543 @@
+#include <wanhelp.h>
+
+PSTR MediumType[] =
+{
+ "NdisMedium802_3",
+ "NdisMedium802_5",
+ "NdisMediumFddi",
+ "NdisMediumWan",
+ "NdisMediumLocalTalk",
+ "NdisMediumDix",
+ "NdisMediumArcnetRaw",
+ "NdisMediumArcnet878_2",
+ "NdisMediumAtm",
+ "NdisMediumWirelessWan",
+ "NdisMediumIrda"
+};
+
+PSTR WanMediumSubtype[] =
+{
+ "NdisWanMediumHub",
+ "NdisWanMediumX_25",
+ "NdisWanMediumIsdn",
+ "NdisWanMediumSerial",
+ "NdisWanMediumFrameRelay",
+ "NdisWanMediumAtm",
+ "NdisWanMediumSonet",
+ "NdisWanMediumSW56K"
+};
+
+PSTR WanHeaderFormat[] =
+{
+ "NdisWanHeaderNative", // src/dest based on subtype, followed by NLPID
+ "NdisWanHeaderEthernet" // emulation of ethernet header
+};
+
+PSTR HardwareStatus[] =
+{
+ "NdisHardwareStatusReady",
+ "NdisHardwareStatusInitializing",
+ "NdisHardwareStatusReset",
+ "NdisHardwareStatusClosing",
+ "NdisHardwareStatusNotReady"
+};
+
+PSTR LinkCBStates[] =
+{
+ "LinkDown",
+ "LinkGoingDown",
+ "LinkUp"
+};
+
+PSTR BundleCBStates[] =
+{
+ "BundleDown",
+ "BundleGowingDown",
+ "BundleUp",
+ "BundleRouted",
+ "BundleUnrouting"
+};
+
+PSTR WanQuality[] =
+{
+ "NdisWanRaw",
+ "NdisWanErrorControl",
+ "NdisWanReliable"
+};
+
+PSTR DeferredQueueDesc[] =
+{
+ "ReceiveIndication",
+ "SendComplete",
+ "StatusIndication",
+ "Loopback"
+};
+
+VOID
+DisplayNdisWanCB(
+ DWORD Address,
+ PNDISWANCB NdisWanCB
+ )
+{
+ dprintf("NdisWanCB: 0x%8.8x\n\n", Address);
+ dprintf(" Lock: 0x%8.8x Irql: 0x%8.8x\n", NdisWanCB->Lock.SpinLock, NdisWanCB->Lock.OldIrql);
+ dprintf(" NdisWrapperHandle: 0x%8.8x\n", NdisWanCB->hNdisWrapperHandle);
+ dprintf(" ProtocolHandle: 0x%8.8x\n", NdisWanCB->hProtocolHandle);
+ dprintf(" NumberOfProtocols: %ld\n", NdisWanCB->ulNumberOfProtocols);
+ dprintf(" NumberOfLinks: %ld\n", NdisWanCB->ulNumberOfLinks);
+ dprintf(" MiniumFragmentSize: 0x%8.8x\n", NdisWanCB->ulMinFragmentSize);
+ dprintf(" TraceLevel: 0x%8.8x\n", NdisWanCB->ulTraceLevel);
+ dprintf(" TraceMask: 0x%8.8x\n", NdisWanCB->ulTraceMask);
+ dprintf(" DriverObject: 0x%8.8x\n", NdisWanCB->pDriverObject);
+ dprintf(" DeviceObject: 0x%8.8x\n", NdisWanCB->pDeviceObject);
+ dprintf(" PacketsSent: %ld\n", NdisWanCB->SendCount);
+ dprintf(" PacketsCompleted: %ld\n", NdisWanCB->SendCompleteCount);
+ dprintf(" IORecvQueueEmpty: %ld\n", NdisWanCB->IORecvError1);
+ dprintf(" IORecvBeforMap: %ld\n", NdisWanCB->IORecvError2);
+ dprintf(" PromiscuousAdapter: 0x%8.8x\n",NdisWanCB->PromiscuousAdapter);
+}
+
+VOID
+DisplayWanAdapterCB(
+ DWORD Address,
+ PWAN_ADAPTERCB WanAdapterCB
+ )
+{
+ dprintf("\n\nWanAdapterCB: 0x%8.8x\n", Address);
+
+ dprintf(" Linkage:\n");
+ dprintf(" Flink: 0x%8.8x Blink: 0x%8.8x\n",
+ WanAdapterCB->Linkage.Flink, WanAdapterCB->Linkage.Blink);
+
+ dprintf(" Lock: 0x%8.8x Irql: 0x%8.8x\n",
+ WanAdapterCB->Lock.SpinLock, WanAdapterCB->Lock.OldIrql);
+
+ dprintf(" FreeLinkCBList:\n");
+ dprintf(" Flink: 0x%8.8x Blink: 0x%8.8x\n",
+ WanAdapterCB->FreeLinkCBList.Flink, WanAdapterCB->FreeLinkCBList.Blink);
+
+ dprintf(" NdisBindingHandle: 0x%8.8x\n", WanAdapterCB->hNdisBindingHandle);
+
+ dprintf(" WanRequest: 0x%8.8x\n", WanAdapterCB->pWanRequest);
+ dprintf(" LastRequest: 0x%8.8x\n", WanAdapterCB->pLastWanRequest);
+
+ dprintf(" MiniportName: Buffer: 0x%8.8x Length: %ld\n",
+ WanAdapterCB->MiniportName.Buffer, WanAdapterCB->MiniportName.Length);
+
+ dprintf(" MediumType: %s\n", MediumType[WanAdapterCB->MediumType]);
+
+ dprintf(" MediumSubType: %s\n", WanMediumSubtype[WanAdapterCB->MediumSubType]);
+
+ dprintf(" WanHeaderFormat: %s\n", WanHeaderFormat[WanAdapterCB->WanHeaderFormat]);
+
+ dprintf(" MaxFrameSize: %ld\n", WanAdapterCB->WanInfo.MaxFrameSize);
+
+ dprintf(" MaxTransmit: %ld\n", WanAdapterCB->WanInfo.MaxTransmit);
+
+ dprintf(" HeaderPadding: %ld\n",WanAdapterCB->WanInfo.HeaderPadding);
+
+ dprintf(" TailPadding: %ld\n",WanAdapterCB->WanInfo.TailPadding);
+
+ dprintf(" Endpoints: %ld\n",WanAdapterCB->WanInfo.Endpoints);
+
+ dprintf(" MemoryFlags: 0x%8.8x\n",WanAdapterCB->WanInfo.MemoryFlags);
+
+ dprintf(" HighestAddress: 0x%8.8x 0x%8.8x\n",
+ WanAdapterCB->WanInfo.HighestAcceptableAddress.HighPart,
+ WanAdapterCB->WanInfo.HighestAcceptableAddress.LowPart);
+
+ dprintf(" FramingBits: 0x%8.8x\n",WanAdapterCB->WanInfo.FramingBits);
+
+ dprintf(" DesiredACCM: 0x%8.8x\n",WanAdapterCB->WanInfo.DesiredACCM);
+}
+
+VOID
+DisplayAdapterCB(
+ DWORD Address,
+ PADAPTERCB AdapterCB
+ )
+{
+ DWORD i;
+
+ dprintf("\n\nAdapterCB: 0x%8.8x\n", Address);
+
+ dprintf(" Linkage:\n");
+ dprintf(" Flink: 0x%8.8x Blink: 0x%8.8x\n",
+ AdapterCB->Linkage.Flink, AdapterCB->Linkage.Blink);
+
+ dprintf(" Lock: 0x%8.8x Irql: 0x%8.8x\n",
+ AdapterCB->Lock.SpinLock, AdapterCB->Lock.OldIrql);
+
+ dprintf(" ReferenceCount: %ld\n", AdapterCB->ulReferenceCount);
+
+ dprintf(" MiniportAdapterHandle: 0x%8.8x\n", AdapterCB->hMiniportHandle);
+
+ dprintf(" Flags: 0x%8.8x\n", AdapterCB->Flags);
+
+ dprintf(" FreeDeferredQueue:\n");
+ dprintf(" Head: 0x%8.8x\n", AdapterCB->FreeDeferredQueue.Head);
+ dprintf(" Tail: 0x%8.8x\n", AdapterCB->FreeDeferredQueue.Tail);
+ dprintf(" Count: %ld\n", AdapterCB->FreeDeferredQueue.Count);
+ dprintf(" MaxCount: %ld\n", AdapterCB->FreeDeferredQueue.MaxCount);
+ for (i = 0; i < MAX_DEFERRED_QUEUE_TYPES; i++) {
+ dprintf(" DeferredQueue: %s\n", DeferredQueueDesc[i]);
+ dprintf(" Head: 0x%8.8x\n", AdapterCB->DeferredQueue[i].Head);
+ dprintf(" Tail: 0x%8.8x\n", AdapterCB->DeferredQueue[i].Tail);
+ dprintf(" Count: %ld\n", AdapterCB->DeferredQueue[i].Count);
+ dprintf(" MaxCount: %ld\n", AdapterCB->DeferredQueue[i].MaxCount);
+ }
+
+ dprintf(" MediumType: %s\n", MediumType[AdapterCB->MediumType]);
+
+ dprintf(" HardwareStatus: %s\n", HardwareStatus[AdapterCB->HardwareStatus]);
+
+ dprintf(" AdapterName: Buffer: 0x%8.8x Length: %d\n",
+ AdapterCB->AdapterName.Buffer, AdapterCB->AdapterName.Length);
+
+ dprintf(" NetworkAddress: 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x\n",
+ AdapterCB->NetworkAddress[0], AdapterCB->NetworkAddress[1], AdapterCB->NetworkAddress[2],
+ AdapterCB->NetworkAddress[3], AdapterCB->NetworkAddress[4], AdapterCB->NetworkAddress[5]);
+
+ dprintf(" NumberOfProtocols: %ld\n", AdapterCB->ulNumberofProtocols);
+
+ dprintf(" ProtocolType: 0x%4.4x\n", AdapterCB->ProtocolType);
+
+ dprintf(" NbfBundleCB: 0x%8.8x\n", AdapterCB->NbfBundleCB);
+ dprintf(" NbfProtocolHandle: 0x%8.8x\n", AdapterCB->NbfProtocolHandle);
+
+}
+
+VOID
+DisplayConnectionTable(
+ DWORD Address,
+ PCONNECTION_TABLE ConnectionTable
+ )
+{
+ dprintf("\n\nConnectionTable: 0x%8.8x\n", Address);
+ dprintf(" Lock: 0x%8.8x Irql: 0x%8.8x\n",
+ ConnectionTable->Lock.SpinLock, ConnectionTable->Lock.OldIrql);
+ dprintf(" AllocationSize: %ld\n", ConnectionTable->ulAllocationSize);
+ dprintf(" ArraySize: %ld\n", ConnectionTable->ulArraySize);
+ dprintf(" Number Of Active Links: %ld\n", ConnectionTable->ulNumActiveLinks);
+ dprintf(" Number Of Active Bundles: %ld\n", ConnectionTable->ulNumActiveBundles);
+ dprintf(" LinkArray: 0x%8.8x\n", ConnectionTable->LinkArray);
+ dprintf(" BundleArray: 0x%8.8x\n", ConnectionTable->BundleArray);
+}
+
+VOID
+DisplayLinkCB(
+ DWORD Address,
+ PLINKCB LinkCB
+ )
+{
+ dprintf("\n\nLinkCB: 0x%8.8x\n", Address);
+ dprintf(" Linkage:\n");
+ dprintf(" Flink: 0x%8.8x Blink: 0x%8.8x\n",
+ LinkCB->Linkage.Flink, LinkCB->Linkage.Blink);
+ dprintf(" Handle: 0x%8.8x\n", LinkCB->hLinkHandle);
+ dprintf(" User Context: 0x%8.8x\n", LinkCB->hLinkContext);
+ dprintf(" ReferenceCount: %ld\n", LinkCB->ulReferenceCount);
+ dprintf(" State: %s\n", LinkCBStates[LinkCB->State]);
+ dprintf(" WanAdapterCB: 0x%8.8x\n", LinkCB->WanAdapterCB);
+ dprintf(" BundleCB: 0x%8.8x\n", LinkCB->BundleCB);
+ dprintf(" WanMiniport Lineup Context: 0x%8.8x\n", LinkCB->NdisLinkHandle);
+ dprintf(" WanPacketPool:\n");
+ dprintf(" Flink: 0x%8.8x Blink: 0x%8.8x\n",
+ LinkCB->WanPacketPool.Flink, LinkCB->WanPacketPool.Blink);
+ dprintf(" WanPacketCount: %ld\n", LinkCB->ulWanPacketCount);
+ dprintf(" OutstandingFrames: %ld\n", LinkCB->OutstandingFrames);
+ dprintf(" LinkBandwidth: %ld\n", LinkCB->ulBandwidth);
+ dprintf(" LinkInfo:\n");
+ dprintf(" MaxSendFrameSize: %ld\n", LinkCB->LinkInfo.MaxSendFrameSize);
+ dprintf(" MaxRecvFrameSize: %ld\n", LinkCB->LinkInfo.MaxRecvFrameSize);
+ dprintf(" HeaderPadding: %ld\n", LinkCB->LinkInfo.HeaderPadding);
+ dprintf(" TailPadding: %ld\n", LinkCB->LinkInfo.TailPadding);
+ dprintf(" SendFramingBits: 0x%8.8x\n", LinkCB->LinkInfo.SendFramingBits);
+ dprintf(" RecvFramingBits: 0x%8.8x\n", LinkCB->LinkInfo.RecvFramingBits);
+ dprintf(" SendCompressionBits: 0x%8.8x\n", LinkCB->LinkInfo.SendCompressionBits);
+ dprintf(" RecvCompressionBits: 0x%8.8x\n", LinkCB->LinkInfo.RecvCompressionBits);
+ dprintf(" SendACCM: 0x%8.8x\n", LinkCB->LinkInfo.SendACCM);
+ dprintf(" RecvACCM: 0x%8.8x\n", LinkCB->LinkInfo.RecvACCM);
+ dprintf(" MaxRSendFrameSize: %ld\n", LinkCB->LinkInfo.MaxRSendFrameSize);
+ dprintf(" MaxRRecvFrameSize: %ld\n", LinkCB->LinkInfo.MaxRRecvFrameSize);
+ dprintf(" LineUpInfo:\n");
+ dprintf(" LinkSpeed: %ld\n", LinkCB->LineUpInfo.LinkSpeed);
+ dprintf(" Quality: 0x%8.8x\n", LinkCB->LineUpInfo.Quality);
+ dprintf(" SendWindow: %d\n", LinkCB->LineUpInfo.SendWindow);
+ dprintf(" ConnectionWrapperID: 0x%8.8x\n", LinkCB->LineUpInfo.ConnectionWrapperID);
+ dprintf(" NdisLinkHandle: 0x%8.8x\n", LinkCB->LineUpInfo.NdisLinkHandle);
+ dprintf(" NdisLinkContext: 0x%8.8x\n", LinkCB->LineUpInfo.NdisLinkContext);
+ dprintf(" FriendlyName: %s\n", LinkCB->Name);
+ dprintf(" LinkStats:\n");
+ dprintf(" BytesTransmitted: %ld\n", LinkCB->LinkStats.BytesTransmitted);
+ dprintf(" BytesReceived: %ld\n", LinkCB->LinkStats.BytesReceived);
+ dprintf(" FramesTransmitted: %ld\n", LinkCB->LinkStats.FramesTransmitted);
+ dprintf(" FramesReceived: %ld\n", LinkCB->LinkStats.FramesReceived);
+
+ dprintf(" CRCErrors: %ld\n", LinkCB->LinkStats.CRCErrors);
+ dprintf(" TimeoutErrors: %ld\n", LinkCB->LinkStats.TimeoutErrors);
+ dprintf(" AlignmentErrors: %ld\n", LinkCB->LinkStats.AlignmentErrors);
+ dprintf(" SerialOverrunErrors: %ld\n", LinkCB->LinkStats.SerialOverrunErrors);
+ dprintf(" FramingErrors: %ld\n", LinkCB->LinkStats.FramingErrors);
+ dprintf(" BufferOverrunErrors: %ld\n", LinkCB->LinkStats.BufferOverrunErrors);
+ dprintf(" ByteTransmittedUncompressed: %ld\n", LinkCB->LinkStats.BytesTransmittedUncompressed);
+ dprintf(" BytesReceivedUncompressed: %ld\n", LinkCB->LinkStats.BytesReceivedUncompressed);
+ dprintf(" BytesTransmittedCompressed: %ld\n", LinkCB->LinkStats.BytesTransmittedCompressed);
+ dprintf(" BytesReceivedCompressed: %ld\n", LinkCB->LinkStats.BytesReceivedCompressed);
+}
+
+VOID
+DisplayBundleCB(
+ DWORD Address,
+ PBUNDLECB BundleCB
+ )
+{
+ DWORD i;
+
+ dprintf("\n\nBundleCB: 0x%8.8x\n", Address);
+ dprintf(" Handle: 0x%8.8x\n",BundleCB->hBundleHandle);
+ dprintf(" ReferenceCount: %ld\n",BundleCB->ulReferenceCount);
+ dprintf(" State: %s\n",BundleCBStates[BundleCB->State]);
+ dprintf(" LinkCBList:\n");
+ dprintf(" Flink: 0x%8.8x Blink: 0x%8.8x\n",
+ BundleCB->LinkCBList.Flink, BundleCB->LinkCBList.Blink);
+ dprintf(" LinkCBCount: %ld\n",BundleCB->ulLinkCBCount);
+ dprintf(" FramingInfo:\n");
+ dprintf(" SendFramingBits: 0x%8.8x\n", BundleCB->FramingInfo.SendFramingBits);
+ dprintf(" RecvFramingBits: 0x%8.8x\n", BundleCB->FramingInfo.RecvFramingBits);
+ dprintf(" MaxRSendFrameSize: %ld\n", BundleCB->FramingInfo.MaxRSendFrameSize);
+ dprintf(" MaxRRecvFrameSize: %ld\n", BundleCB->FramingInfo.MaxRRecvFrameSize);
+ dprintf(" NextLinkToXmit: 0x%8.8x\n",BundleCB->NextLinkToXmit);
+ dprintf(" SendingLinks: %d\n", BundleCB->SendingLinks);
+ dprintf(" SendPacketQueue:\n");
+ dprintf(" Flink: 0x%8.8x Blink: 0x%8.8x\n",
+ BundleCB->SendPacketQueue.Flink, BundleCB->SendPacketQueue.Blink);
+ dprintf(" SendSequenceNumber: 0x%8.8x\n", BundleCB->SendSeqNumber);
+ dprintf(" MaxSendSequenceNumber: 0x%8.8x\n", BundleCB->MaxSendSeqNumber);
+ dprintf(" SendSequenceMask: 0x%8.8x\n", BundleCB->SendSeqMask);
+ dprintf(" Flags: 0x%8.8x\n",BundleCB->Flags);
+ dprintf(" OutstandingFrames: %ld\n",BundleCB->OutstandingFrames);
+ dprintf(" RecvDescPool:\n");
+ dprintf(" Flink: 0x%8.8x Blink: 0x%8.8x\n",
+ BundleCB->RecvDescPool.Flink, BundleCB->RecvDescPool.Blink);
+ dprintf(" RecvDesc Count: %ld\n", BundleCB->RecvDescCount);
+ dprintf(" RecvDesc Max Count: %ld\n", BundleCB->RecvDescMax);
+ dprintf(" RecvDescAssemblyList:\n");
+ dprintf(" Flink: 0x%8.8x Blink: 0x%8.8x\n",
+ BundleCB->RecvDescAssemblyList.Flink, BundleCB->RecvDescAssemblyList.Blink);
+ dprintf(" RecvDescHole: 0x%8.8x\n", BundleCB->RecvDescHole);
+ dprintf(" MaxRecvSeqNumber: 0x%8.8x\n", BundleCB->MaxRecvSeqNumber);
+ dprintf(" RecvSeqMask: 0x%8.8x\n", BundleCB->RecvSeqMask);
+ dprintf(" TimeToLive: %ld\n", BundleCB->TimeToLive);
+ dprintf(" RecvFragmentsLost: %ld\n", BundleCB->RecvFragmentsLost);
+ dprintf(" ProtocolCBTable: 0x%8.8x\n",BundleCB->ProtocolCBTable);
+ dprintf(" Number Of Routes: %ld\n",BundleCB->ulNumberOfRoutes);
+ dprintf(" ProtocolCBList:\n");
+ dprintf(" Flink: 0x%8.8x Blink: 0x%8.8x\n",
+ BundleCB->ProtocolCBList.Flink, BundleCB->ProtocolCBList.Blink);
+ dprintf(" SendMask: 0x%8.8x\n",BundleCB->SendMask);
+ dprintf(" LineUpInfo:\n");
+ dprintf(" BundleSpeed: %ld\n", BundleCB->LineUpInfo.BundleSpeed);
+ dprintf(" MaxSendSize: %ld\n", BundleCB->LineUpInfo.ulMaximumTotalSize);
+ dprintf(" LinkQuality: %s\n", WanQuality[BundleCB->LineUpInfo.Quality]);
+ dprintf(" SendWindow: %d\n", BundleCB->LineUpInfo.usSendWindow);
+ dprintf(" SendVJInfo:\n");
+ dprintf(" IPCompressionProtocol: 0x%4.4x\n", BundleCB->SendVJInfo.IPCompressionProtocol);
+ dprintf(" MaxSlotID: %d\n", BundleCB->SendVJInfo.MaxSlotID);
+ dprintf(" CompSlotID: %d\n", BundleCB->SendVJInfo.CompSlotID);
+ dprintf(" VJCompress: 0x%8.8x\n", BundleCB->SendVJCompress);
+ dprintf(" RecvVJInfo:\n");
+ dprintf(" IPCompressionProtocol: 0x%4.4x\n", BundleCB->RecvVJInfo.IPCompressionProtocol);
+ dprintf(" MaxSlotID: %d\n", BundleCB->RecvVJInfo.MaxSlotID);
+ dprintf(" CompSlotID: %d\n", BundleCB->RecvVJInfo.CompSlotID);
+ dprintf(" VJCompress: 0x%8.8x\n", BundleCB->RecvVJCompress);
+ dprintf(" SendCompInfo:\n");
+ dprintf(" SessionKey: 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x\n",
+ BundleCB->SendCompInfo.SessionKey[0],BundleCB->SendCompInfo.SessionKey[1],
+ BundleCB->SendCompInfo.SessionKey[2],BundleCB->SendCompInfo.SessionKey[3],
+ BundleCB->SendCompInfo.SessionKey[4],BundleCB->SendCompInfo.SessionKey[5],
+ BundleCB->SendCompInfo.SessionKey[6],BundleCB->SendCompInfo.SessionKey[7]);
+ dprintf(" MSCompType: 0x%8.8x\n", BundleCB->SendCompInfo.MSCompType);
+ dprintf(" SendCompressContext: 0x%8.8x\n", BundleCB->SendCompressContext);
+ dprintf(" RecvCompInfo:\n");
+ dprintf(" SessionKey: 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x\n",
+ BundleCB->RecvCompInfo.SessionKey[0],BundleCB->RecvCompInfo.SessionKey[1],
+ BundleCB->RecvCompInfo.SessionKey[2],BundleCB->RecvCompInfo.SessionKey[3],
+ BundleCB->RecvCompInfo.SessionKey[4],BundleCB->RecvCompInfo.SessionKey[5],
+ BundleCB->RecvCompInfo.SessionKey[6],BundleCB->RecvCompInfo.SessionKey[7]);
+ dprintf(" MSCompType: 0x%8.8x\n", BundleCB->RecvCompInfo.MSCompType);
+ dprintf(" RecvCompressContext: 0x%8.8x\n", BundleCB->RecvCompressContext);
+ dprintf(" SendRC4Key: 0x%8.8x\n", BundleCB->SendRC4Key);
+ dprintf(" RecvRC4Key: 0x%8.8x\n", BundleCB->RecvRC4Key);
+ dprintf(" SCoherencyCounter: 0x%4.4x\n", BundleCB->SCoherencyCounter);
+ dprintf(" RCoherencyCounter: 0x%4.4x\n", BundleCB->RCoherencyCounter);
+ dprintf(" LastRC4Reset: 0x%4.4x\n", BundleCB->LastRC4Reset);
+ dprintf(" CCPIdentifier: 0x%4.4x\n", BundleCB->CCPIdentifier);
+ dprintf(" UpperBonDInfo:\n");
+ dprintf(" BytesThreshold: %ld\n", BundleCB->UpperBonDInfo.ulBytesThreshold);
+ dprintf(" PercentBandwidth: %d\n", BundleCB->UpperBonDInfo.usPercentBandwidth);
+ dprintf(" SecondsInSamplePeriod: %ld\n", BundleCB->UpperBonDInfo.ulSecondsInSamplePeriod);
+ dprintf(" State: 0x%8.8x\n", BundleCB->UpperBonDInfo.State);
+ dprintf(" StartTime: 0x%8.8x%8.8x\n",
+ BundleCB->UpperBonDInfo.StartTime.HighPart, BundleCB->UpperBonDInfo.StartTime.LowPart);
+ dprintf(" SampleTable:\n");
+ dprintf(" FirstIndex: %ld\n", BundleCB->UpperBonDInfo.SampleTable.ulFirstIndex);
+ dprintf(" CurrentIndex: %ld\n", BundleCB->UpperBonDInfo.SampleTable.ulCurrentIndex);
+ dprintf(" CurrentSampleByteCount: %ld\n", BundleCB->UpperBonDInfo.SampleTable.ulCurrentSampleByteCount);
+ dprintf(" SampleArraySize: %ld\n", BundleCB->UpperBonDInfo.SampleTable.ulSampleArraySize);
+ dprintf(" SampleRate: 0x%8.8x%8.8x\n",
+ BundleCB->UpperBonDInfo.SampleTable.SampleRate.HighPart, BundleCB->UpperBonDInfo.SampleTable.SampleRate.LowPart);
+ dprintf(" SamplePeriod: 0x%8.8x%8.8x\n",
+ BundleCB->UpperBonDInfo.SampleTable.SamplePeriod.HighPart, BundleCB->UpperBonDInfo.SampleTable.SamplePeriod.LowPart);
+ dprintf(" SampleTable:\n");
+ for (i = 0; i < SAMPLE_ARRAY_SIZE; i++) {
+ dprintf(" Sample %d:\n", i);
+ dprintf(" BytesThisSend: %ld\n",BundleCB->UpperBonDInfo.SampleTable.SampleArray[i].ulBytesThisSend);
+ dprintf(" ReferenceCount: %ld\n",BundleCB->UpperBonDInfo.SampleTable.SampleArray[i].ulReferenceCount);
+ dprintf(" TimeStample: 0x%8.8x%8.8x\n",
+ BundleCB->UpperBonDInfo.SampleTable.SampleArray[i].TimeStamp.HighPart, BundleCB->UpperBonDInfo.SampleTable.SampleArray[i].TimeStamp.LowPart);
+ }
+ dprintf(" LowerBonDInfo:\n");
+ dprintf(" BytesThreshold: %ld\n", BundleCB->LowerBonDInfo.ulBytesThreshold);
+ dprintf(" PercentBandwidth: %d\n", BundleCB->LowerBonDInfo.usPercentBandwidth);
+ dprintf(" SecondsInSamplePeriod: %ld\n", BundleCB->LowerBonDInfo.ulSecondsInSamplePeriod);
+ dprintf(" State: 0x%8.8x\n", BundleCB->LowerBonDInfo.State);
+ dprintf(" StartTime: 0x%8.8x%8.8x\n",
+ BundleCB->LowerBonDInfo.StartTime.HighPart, BundleCB->LowerBonDInfo.StartTime.LowPart);
+ dprintf(" SampleTable:\n");
+ dprintf(" FirstIndex: %ld\n", BundleCB->LowerBonDInfo.SampleTable.ulFirstIndex);
+ dprintf(" CurrentIndex: %ld\n", BundleCB->LowerBonDInfo.SampleTable.ulCurrentIndex);
+ dprintf(" CurrentSampleByteCount: %ld\n", BundleCB->LowerBonDInfo.SampleTable.ulCurrentSampleByteCount);
+ dprintf(" SampleArraySize: %ld\n", BundleCB->LowerBonDInfo.SampleTable.ulSampleArraySize);
+ dprintf(" SampleRate: 0x%8.8x%8.8x\n",
+ BundleCB->LowerBonDInfo.SampleTable.SampleRate.HighPart, BundleCB->LowerBonDInfo.SampleTable.SampleRate.LowPart);
+ dprintf(" SamplePeriod: 0x%8.8x%8.8x\n",
+ BundleCB->LowerBonDInfo.SampleTable.SamplePeriod.HighPart, BundleCB->LowerBonDInfo.SampleTable.SamplePeriod.LowPart);
+ dprintf(" SampleArray:\n");
+ for (i = 0; i < SAMPLE_ARRAY_SIZE; i++) {
+ dprintf(" Sample %d:\n", i);
+ dprintf(" BytesThisSend: %ld\n",BundleCB->LowerBonDInfo.SampleTable.SampleArray[i].ulBytesThisSend);
+ dprintf(" ReferenceCount: %ld\n",BundleCB->LowerBonDInfo.SampleTable.SampleArray[i].ulReferenceCount);
+ dprintf(" TimeStample: 0x%8.8x%8.8x\n",
+ BundleCB->LowerBonDInfo.SampleTable.SampleArray[i].TimeStamp.HighPart, BundleCB->LowerBonDInfo.SampleTable.SampleArray[i].TimeStamp.LowPart);
+ }
+ dprintf(" FriendlyName: %s\n", BundleCB->Name);
+ dprintf(" BundleStats:\n");
+ dprintf(" BytesTransmitted: %ld\n", BundleCB->BundleStats.BytesTransmitted);
+ dprintf(" BytesReceived: %ld\n", BundleCB->BundleStats.BytesReceived);
+ dprintf(" FramesTransmitted: %ld\n", BundleCB->BundleStats.FramesTransmitted);
+ dprintf(" FramesReceived: %ld\n", BundleCB->BundleStats.FramesReceived);
+
+ dprintf(" CRCErrors: %ld\n", BundleCB->BundleStats.CRCErrors);
+ dprintf(" TimeoutErrors: %ld\n", BundleCB->BundleStats.TimeoutErrors);
+ dprintf(" AlignmentErrors: %ld\n", BundleCB->BundleStats.AlignmentErrors);
+ dprintf(" SerialOverrunErrors: %ld\n", BundleCB->BundleStats.SerialOverrunErrors);
+ dprintf(" FramingErrors: %ld\n", BundleCB->BundleStats.FramingErrors);
+ dprintf(" BufferOverrunErrors: %ld\n", BundleCB->BundleStats.BufferOverrunErrors);
+ dprintf(" ByteTransmittedUncompressed: %ld\n", BundleCB->BundleStats.BytesTransmittedUncompressed);
+ dprintf(" BytesReceivedUncompressed: %ld\n", BundleCB->BundleStats.BytesReceivedUncompressed);
+ dprintf(" BytesTransmittedCompressed: %ld\n", BundleCB->BundleStats.BytesTransmittedCompressed);
+ dprintf(" BytesReceivedCompressed: %ld\n", BundleCB->BundleStats.BytesReceivedCompressed);
+}
+
+VOID
+DisplayProtocolCB(
+ DWORD Address,
+ PPROTOCOLCB ProtocolCB
+ )
+{
+ DWORD i;
+
+ dprintf("\n\nProtocolCB: 0x%8.8x\n", Address);
+ dprintf(" Linkage:\n");
+ dprintf(" Flink: 0x%8.8x Blink: 0x%8.8x\n",
+ ProtocolCB->Linkage.Flink, ProtocolCB->Linkage.Blink);
+ dprintf(" ProtocolHandle: 0x%8.8x\n", ProtocolCB->hProtocolHandle);
+ dprintf(" ReferenceCount: %ld\n", ProtocolCB->ulReferenceCount);
+ dprintf(" HeadNdisPacketQueue: 0x%8.8x\n", ProtocolCB->HeadNdisPacketQueue);
+ dprintf(" TailNdisPacketQueue: 0x%8.8x\n", ProtocolCB->TailNdisPacketQueue);
+ dprintf(" SendMaskBit: 0x%8.8x\n", ProtocolCB->SendMaskBit);
+ dprintf(" AdapterCB: 0x%8.8x\n", ProtocolCB->AdapterCB);
+ dprintf(" BundleCB: 0x%8.8x\n", ProtocolCB->BundleCB);
+ dprintf(" Flags: 0x%8.8x\n", ProtocolCB->Flags);
+ dprintf(" ProtocolType: 0x%4.4x\n", ProtocolCB->usProtocolType);
+ dprintf(" PPP ProtocolID: 0x%4.4x\n", ProtocolCB->usPPPProtocolID);
+ dprintf(" Priority: %ld\n", ProtocolCB->usPriority);
+ dprintf(" Bytes Quota: %ld\n", ProtocolCB->ulByteQuota);
+ dprintf(" SampleTable:\n");
+ dprintf(" FirstIndex: %ld\n", ProtocolCB->SampleTable.ulFirstIndex);
+ dprintf(" CurrentIndex: %ld\n", ProtocolCB->SampleTable.ulCurrentIndex);
+ dprintf(" CurrentSampleByteCount: %ld\n", ProtocolCB->SampleTable.ulCurrentSampleByteCount);
+ dprintf(" SampleArraySize: %ld\n", ProtocolCB->SampleTable.ulSampleArraySize);
+ dprintf(" SampleRate: 0x%8.8x%8.8x\n",
+ ProtocolCB->SampleTable.SampleRate.HighPart, ProtocolCB->SampleTable.SampleRate.LowPart);
+ dprintf(" SamplePeriod: 0x%8.8x%8.8x\n",
+ ProtocolCB->SampleTable.SamplePeriod.HighPart, ProtocolCB->SampleTable.SamplePeriod.LowPart);
+ dprintf(" SampleArray:\n");
+ for (i = 0; i < SAMPLE_ARRAY_SIZE; i++) {
+ dprintf(" Sample %d:\n", i);
+ dprintf(" BytesThisSend: %ld\n",ProtocolCB->SampleTable.SampleArray[i].ulBytesThisSend);
+ dprintf(" ReferenceCount: %ld\n",ProtocolCB->SampleTable.SampleArray[i].ulReferenceCount);
+ dprintf(" TimeStample: 0x%8.8x%8.8x\n",
+ ProtocolCB->SampleTable.SampleArray[i].TimeStamp.HighPart, ProtocolCB->SampleTable.SampleArray[i].TimeStamp.LowPart);
+ }
+ dprintf(" TransportHandle: 0x%8.8x\n", ProtocolCB->hTransportHandle);
+ dprintf(" NdisWanAddress: 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x\n",
+ ProtocolCB->NdisWanAddress[0], ProtocolCB->NdisWanAddress[1], ProtocolCB->NdisWanAddress[2],
+ ProtocolCB->NdisWanAddress[3], ProtocolCB->NdisWanAddress[4], ProtocolCB->NdisWanAddress[5]);
+ dprintf(" TransportAddress: 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x\n",
+ ProtocolCB->TransportAddress[0], ProtocolCB->TransportAddress[1], ProtocolCB->TransportAddress[2],
+ ProtocolCB->TransportAddress[3], ProtocolCB->TransportAddress[4], ProtocolCB->TransportAddress[5]);
+ dprintf(" DeviceName: Buffer: 0x%8.8x Length: %ld\n",
+ ProtocolCB->DeviceName.Buffer, ProtocolCB->DeviceName.Length);
+}
+
+VOID
+DisplayWanPacket(
+ DWORD Address,
+ PNDIS_WAN_PACKET Packet
+ )
+{
+
+ dprintf("\n\nWanPacket: 0x%8.8x\n", Address);
+ dprintf(" WanPacketQueue:\n");
+ dprintf(" Flink: 0x%8.8x Blink: 0x%8.8x\n",
+ Packet->WanPacketQueue.Flink, Packet->WanPacketQueue.Blink);
+ dprintf(" CurrentBuffer: 0x%8.8x\n", Packet->CurrentBuffer);
+ dprintf(" CurrentLength: %ld\n", Packet->CurrentLength);
+ dprintf(" StartBuffer: 0x%8.8x\n", Packet->StartBuffer);
+ dprintf(" EndBuffer: 0x%8.8x\n", Packet->EndBuffer);
+ dprintf(" PR1 (LinkCB): 0x%8.8x\n", Packet->ProtocolReserved1);
+ dprintf(" PR2 (NdisPacket): 0x%8.8x\n", Packet->ProtocolReserved2);
+ dprintf(" PR3 (ProtocolCB): 0x%8.8x\n", Packet->ProtocolReserved3);
+ dprintf(" PR4 (BytesSent): %ld\n", Packet->ProtocolReserved4);
+ dprintf(" MR1: 0x%8.8x\n", Packet->MacReserved1);
+ dprintf(" MR2: 0x%8.8x\n", Packet->MacReserved2);
+ dprintf(" MR3: 0x%8.8x\n", Packet->MacReserved3);
+ dprintf(" MR4: 0x%8.8x\n", Packet->MacReserved4);
+}
+
+VOID
+DisplayNdisPacket(
+ DWORD Address,
+ PNDIS_PACKET Packet
+ )
+{
+
+ dprintf("\n\nNdisPacket: 0x%8.8x\n", Address);
+ dprintf(" Private:\n");
+ dprintf(" PhysicalCount: 0x%8.8x\n", Packet->Private.PhysicalCount);
+ dprintf(" TotalLength: %ld\n", Packet->Private.TotalLength);
+ dprintf(" BufferHead: 0x%8.8x\n", Packet->Private.Head);
+ dprintf(" BufferTail: 0x%8.8x\n", Packet->Private.Tail);
+ dprintf(" Pool: 0x%8.8x\n", Packet->Private.Pool);
+ dprintf(" Count: 0x%8.8x\n", Packet->Private.Count);
+ dprintf(" Flags: 0x%8.8x\n", Packet->Private.Flags);
+ dprintf(" ValidCounts: %d\n", Packet->Private.ValidCounts);
+ dprintf(" MR1 (Next/MagicNumber): 0x%8.8x\n", *((PDWORD)&Packet->MiniportReserved[0]));
+ dprintf(" MR2 (ReferenceCount): 0x%4.4x (Flags): 0x%4.4x\n",
+ *((PWORD)&Packet->MiniportReserved[4]),*((PWORD)&Packet->MiniportReserved[6]));
+ dprintf(" WR1: 0x%8.8x\n", *((PDWORD)&Packet->WrapperReserved[0]));
+ dprintf(" WR2: 0x%8.8x\n", *((PDWORD)&Packet->WrapperReserved[4]));
+}
+
diff --git a/private/ntos/ndis/ndiswan/kdexts/display.h b/private/ntos/ndis/ndiswan/kdexts/display.h
new file mode 100644
index 000000000..58795a3b9
--- /dev/null
+++ b/private/ntos/ndis/ndiswan/kdexts/display.h
@@ -0,0 +1,54 @@
+VOID
+DisplayNdisWanCB(
+ DWORD Address,
+ PNDISWANCB NdisWanCB
+ );
+
+VOID
+DisplayWanAdapterCB(
+ ULONG Address,
+ PWAN_ADAPTERCB WanAdapterCB
+ );
+
+VOID
+DisplayAdapterCB(
+ ULONG Address,
+ PADAPTERCB AdapterCB
+ );
+
+VOID
+DisplayConnectionTable(
+ DWORD Address,
+ PCONNECTION_TABLE ConnectionTable
+ );
+
+VOID
+DisplayBundleCB(
+ DWORD Address,
+ PBUNDLECB BundleCB
+ );
+
+VOID
+DisplayProtocolCB(
+ DWORD Address,
+ PPROTOCOLCB ProtocolCB
+ );
+
+VOID
+DisplayLinkCB(
+ DWORD Address,
+ PLINKCB LinkCB
+ );
+
+VOID
+DisplayWanPacket(
+ DWORD Address,
+ PNDIS_WAN_PACKET Packet
+ );
+
+VOID
+DisplayNdisPacket(
+ DWORD Address,
+ PNDIS_PACKET Packet
+ );
+
diff --git a/private/ntos/ndis/ndiswan/kdexts/makefile b/private/ntos/ndis/ndiswan/kdexts/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/ntos/ndis/ndiswan/kdexts/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/ntos/ndis/ndiswan/kdexts/sources b/private/ntos/ndis/ndiswan/kdexts/sources
new file mode 100644
index 000000000..32e7d2812
--- /dev/null
+++ b/private/ntos/ndis/ndiswan/kdexts/sources
@@ -0,0 +1,49 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Tony Bell (tonybe)
+
+!ENDIF
+
+TARGETNAME=wanhelp
+DLLBASE=0x58400000
+TARGETPATH=obj
+TARGETTYPE=DYNLINK
+
+INCLUDES=..\;..\..\inc;..\..\..\inc;..\..\..\..\inc;..\..\..\..\..\public\sdk\inc
+
+C_DEFINES=-DNT -DNDIS_WRAPPER
+
+DLLENTRY=_DllMainCRTStartup
+
+SOURCES=wanhelp.c \
+ display.c \
+ api.c \
+ wanhelp.rc
+
+UMTYPE=console
+USE_CRTDLL=1
+DLLBASE=0x1000000
+
+MSC_WARNING_LEVEL=/W3
+
+LINKLIBS=\
+ $(BASEDIR)\public\sdk\lib\*\kernel32.lib
+# $(BASEDIR)\public\sdk\lib\*\kernel32.lib \
+# $(BASEDIR)\public\sdk\lib\*\libcmt.lib
+
diff --git a/private/ntos/ndis/ndiswan/kdexts/wanhelp.c b/private/ntos/ndis/ndiswan/kdexts/wanhelp.c
new file mode 100644
index 000000000..e2c8b0c0c
--- /dev/null
+++ b/private/ntos/ndis/ndiswan/kdexts/wanhelp.c
@@ -0,0 +1,183 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ kdexts.c
+
+Abstract:
+
+ This file contains the generic routines and initialization code
+ for the kernel debugger extensions dll.
+
+Author:
+
+
+Environment:
+
+ User Mode
+
+--*/
+
+#include <wanhelp.h>
+
+//
+// globals
+//
+EXT_API_VERSION ApiVersion = { 3, 5, EXT_API_VERSION_NUMBER, 0 };
+WINDBG_EXTENSION_APIS ExtensionApis;
+ULONG STeip;
+ULONG STebp;
+ULONG STesp;
+USHORT SavedMajorVersion;
+USHORT SavedMinorVersion;
+VOID UnicodeToAnsi(PWSTR pws,PSTR ps, ULONG cbLength);
+CHAR Name[1024];
+
+PSTR gApiDescriptions[] =
+{
+ "help - What do you think your reading?\n",
+ "ndiswancb - Dump the contents of the main NdisWan control structure\n",
+ "enumwanadaptercb - Dump the head of the WanAdapterCB list\n",
+ "wanadaptercb - Dump the contents of a Wan Miniport Adapter structure\n",
+ "enumadaptercb - Dump the head of the AdapterCB list\n",
+ "adaptercb - Dump the contents of a NdisWan Adapter structure\n",
+ "connectiontable - Dump the connetion table\n",
+ "bundlecb - Dump the bundlecb\n",
+ "linkcb - Dump the linkcb\n",
+ "protocolcb - Dump the protocolcb\n",
+ "wanpacket - Dump the wanpacket\n",
+ "ndispacket - Dump the ndispacket\n",
+};
+
+#define MAX_APIS 12
+
+//
+// THESE ARE NEEDED FOR THE KDEXT DLLs
+//
+BOOLEAN
+DllInit(
+ HANDLE hModule,
+ DWORD dwReason,
+ DWORD dwReserved
+ )
+{
+ switch (dwReason) {
+ case DLL_THREAD_ATTACH:
+ DbgBreakPoint();
+ break;
+
+ case DLL_THREAD_DETACH:
+ break;
+
+ case DLL_PROCESS_DETACH:
+ break;
+
+ case DLL_PROCESS_ATTACH:
+ break;
+ }
+
+ return TRUE;
+}
+
+
+//
+// THESE ARE NEEDED FOR THE KDEXT DLLs
+//
+VOID
+WinDbgExtensionDllInit(
+ PWINDBG_EXTENSION_APIS lpExtensionApis,
+ USHORT MajorVersion,
+ USHORT MinorVersion
+ )
+{
+ ExtensionApis = *lpExtensionApis;
+
+ SavedMajorVersion = MajorVersion;
+ SavedMinorVersion = MinorVersion;
+
+ return;
+}
+
+//
+// THESE ARE NEEDED FOR THE KDEXT DLLs
+//
+DECLARE_API( version )
+{
+#if DBG
+ PCHAR DebuggerType = "Checked";
+#else
+ PCHAR DebuggerType = "Free";
+#endif
+
+ dprintf( "%s Extension dll for Build %d debugging %s kernel for Build %d\n",
+ DebuggerType,
+ VER_PRODUCTBUILD,
+ SavedMajorVersion == 0x0c ? "Checked" : "Free",
+ SavedMinorVersion
+ );
+}
+
+//
+// THESE ARE NEEDED FOR THE KDEXT DLLs
+//
+VOID
+CheckVersion(
+ VOID
+ )
+{
+#if DBG
+ if ((SavedMajorVersion != 0x0c) || (SavedMinorVersion != VER_PRODUCTBUILD)) {
+ dprintf("\r\n*** Extension DLL(%d Checked) does not match target system(%d %s)\r\n\r\n",
+ VER_PRODUCTBUILD, SavedMinorVersion, (SavedMajorVersion==0x0f) ? "Free" : "Checked" );
+ }
+#else
+ if ((SavedMajorVersion != 0x0f) || (SavedMinorVersion != VER_PRODUCTBUILD)) {
+ dprintf("\r\n*** Extension DLL(%d Free) does not match target system(%d %s)\r\n\r\n",
+ VER_PRODUCTBUILD, SavedMinorVersion, (SavedMajorVersion==0x0f) ? "Free" : "Checked" );
+ }
+#endif
+}
+
+LPEXT_API_VERSION
+ExtensionApiVersion(
+ VOID
+ )
+{
+ return &ApiVersion;
+}
+
+/*++
+ Try and keep an accurate list of commands.
+--*/
+DECLARE_API(help)
+{
+ UINT c;
+
+ if (0 == args[0]) {
+ for (c = 0; c < MAX_APIS; c++)
+ dprintf(gApiDescriptions[c]);
+ return;
+ }
+}
+
+VOID
+UnicodeToAnsi(
+ PWSTR pws,
+ PSTR ps,
+ ULONG cbLength
+ )
+{
+ PSTR Dest = ps;
+ PWSTR Src = pws;
+ ULONG Length = cbLength;
+
+ dprintf("Enter UnicodeToAnsi\n");
+
+ while (Length--) {
+ *Dest++ = (CHAR)*Src++;
+ }
+
+ dprintf("Exit UnicodeToAnsi\n");
+}
diff --git a/private/ntos/ndis/ndiswan/kdexts/wanhelp.def b/private/ntos/ndis/ndiswan/kdexts/wanhelp.def
new file mode 100644
index 000000000..8acaae7a4
--- /dev/null
+++ b/private/ntos/ndis/ndiswan/kdexts/wanhelp.def
@@ -0,0 +1,48 @@
+;--------------------------------------------------------------------
+;
+; when modifying this file please be aware that the common portions
+; are stored in ..\kdextdef.src. Put your extension in the correct
+; alphabetical order. all extension names must be in lower case!
+;
+;--------------------------------------------------------------------
+
+LIBRARY wanhelp
+
+DESCRIPTION 'Kernel Debugger Extensions Api Library - NdisWan'
+
+EXPORTS
+
+;--------------------------------------------------------------------
+;
+; these are the common exports that all dlls contain
+;
+;--------------------------------------------------------------------
+ help
+ ndiswancb
+ enumwanadaptercb
+ wanadaptercb
+ enumadaptercb
+ adaptercb
+ connectiontable
+ bundlecb
+ linkcb
+ protocolcb
+ wanpacket
+ ndispacket
+
+;--------------------------------------------------------------------
+;
+; these are the i386 specific exports
+;
+;--------------------------------------------------------------------
+
+
+;--------------------------------------------------------------------
+;
+; these are the extension service functions provided for the debugger
+;
+;--------------------------------------------------------------------
+
+ CheckVersion
+ WinDbgExtensionDllInit
+ ExtensionApiVersion
diff --git a/private/ntos/ndis/ndiswan/kdexts/wanhelp.h b/private/ntos/ndis/ndiswan/kdexts/wanhelp.h
new file mode 100644
index 000000000..00016d3c6
--- /dev/null
+++ b/private/ntos/ndis/ndiswan/kdexts/wanhelp.h
@@ -0,0 +1,99 @@
+/*++
+
+ Copyright (c) 1993 Microsoft Corporation
+
+ Module Name:
+
+ wanhelp
+
+ Abstract:
+
+
+ Author:
+
+ Thanks - Kyle Brandon
+
+ History:
+
+--*/
+
+#ifndef __WANHELP_H
+#define __WANHELP_H
+
+//
+// Get rid of as much of Windows as possible
+//
+
+#define NOGDICAPMASKS
+#define NOVIRTUALKEYCODES
+#define NOWINMESSAGES
+#define NOWINSTYLES
+#define NOSYSMETRICS
+#define NOMENUS
+#define NOICONS
+#define NOKEYSTATES
+#define NOSYSCOMMANDS
+#define NORASTEROPS
+#define NOSHOWWINDOW
+#define OEMRESOURCE
+#define NOATOM
+#define NOCLIPBOARD
+#define NOCOLOR
+#define NOCTLMGR
+#define NODRAWTEXT
+#define NOGDI
+#define NOKERNEL
+#define NOUSER
+#define NONLS
+#define NOMB
+#define NOMEMMGR
+#define NOMETAFILE
+#define NOMINMAX
+#define NOMSG
+#define NOOPENFILE
+#define NOSCROLL
+#define NOSERVICE
+#define NOSOUND
+#define NOTEXTMETRIC
+#define NOWH
+#define NOWINOFFSETS
+#define NOCOMM
+#define NOKANJI
+#define NOHELP
+#define NOPROFILER
+#define NODEFERWINDOWPOS
+
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <ntos.h>
+#include <srb.h>
+#include <io.h>
+#include <windows.h>
+#include <imagehlp.h>
+#include <wdbgexts.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ntverp.h>
+//#include <ndismain.h>
+//#include <ndismac.h>
+//#include <ndismini.h>
+//#include <ndiswan.h>
+#include "wan.h"
+#include "display.h"
+
+//
+// support routines.
+//
+VOID UnicodeToAnsi(PWSTR pws, PSTR ps, ULONG cbLength);
+
+
+//
+// Internal definitions
+//
+
+#define NOT_IMPLEMENTED 0xFACEFEED
+
+
+#endif // __WANHELP_H
+
diff --git a/private/ntos/ndis/ndiswan/kdexts/wanhelp.rc b/private/ntos/ndis/ndiswan/kdexts/wanhelp.rc
new file mode 100644
index 000000000..937dbf7b9
--- /dev/null
+++ b/private/ntos/ndis/ndiswan/kdexts/wanhelp.rc
@@ -0,0 +1,12 @@
+#include <windows.h>
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "Microsoft\256 Kernel Debugger Extensions"
+
+#define VER_INTERNALNAME_STR "KDEXTxxx.DLL"
+#define VER_ORIGINALFILENAME_STR "KDEXTxxx.DLL"
+
+#include <common.ver>
+
diff --git a/private/ntos/ndis/ndiswan/loopback.c b/private/ntos/ndis/ndiswan/loopback.c
new file mode 100644
index 000000000..a7702da3b
--- /dev/null
+++ b/private/ntos/ndis/ndiswan/loopback.c
@@ -0,0 +1,148 @@
+/*++
+
+Copyright (c) 1990-1995 Microsoft Corporation
+
+Module Name:
+
+ Loopback.c
+
+Abstract:
+
+ This file contains the procedures for doing loopback of send
+ packets for ndiswan. Loopback is being done in NdisWan because
+ the NDIS wrapper could not meet all of the needs of NdisWan.
+
+Author:
+
+ Tony Bell (TonyBe) January 25, 1996
+
+Environment:
+
+ Kernel Mode
+
+Revision History:
+
+ TonyBe 01/25/96 Created
+
+--*/
+
+#include "wan.h"
+
+VOID
+NdisWanQueueLoopbackPacket(
+ PADAPTERCB AdapterCB,
+ PNDIS_PACKET NdisPacket
+ )
+{
+ PLOOPBACK_DESC LoopbackDesc;
+ ULONG AllocationSize, BufferLength;
+
+ NdisWanDbgOut(DBG_TRACE, DBG_LOOPBACK, ("NdisWanQueueLoopbackPacket: Enter"));
+ NdisWanDbgOut(DBG_INFO, DBG_LOOPBACK, ("AdapterCB: 0x%8.8x, NdisPacket: 0x%8.8x",
+ AdapterCB, NdisPacket));
+
+ //
+ // Create a loopback descriptor
+ //
+ NdisQueryPacket(NdisPacket,
+ NULL,
+ NULL,
+ NULL,
+ &BufferLength);
+
+ AllocationSize = BufferLength + sizeof(LOOPBACK_DESC);
+
+ NdisWanAllocateMemory(&LoopbackDesc, AllocationSize);
+
+ if (LoopbackDesc != NULL) {
+ ULONG BytesCopied;
+ PDEFERRED_DESC DeferredDesc;
+
+ //
+ // For loopback we do not care about the bundlecb/protocolcb
+ // states so they will remain NULL.
+ //
+ LoopbackDesc->AllocationSize = (USHORT)AllocationSize;
+ LoopbackDesc->BufferLength = (USHORT)BufferLength;
+ LoopbackDesc->Buffer = (PUCHAR)LoopbackDesc + sizeof(LOOPBACK_DESC);
+
+ //
+ // Copy the current packet
+ //
+ NdisWanCopyFromPacketToBuffer(NdisPacket,
+ 0,
+ 0xFFFFFFFF,
+ LoopbackDesc->Buffer,
+ &BytesCopied);
+
+ ASSERT(BytesCopied == BufferLength);
+
+ NdisAcquireSpinLock(&AdapterCB->Lock);
+
+ NdisWanGetDeferredDesc(AdapterCB, &DeferredDesc);
+
+ ASSERT(DeferredDesc != NULL);
+
+ DeferredDesc->Context = (PVOID)LoopbackDesc;
+
+ InsertTailDeferredQueue(&AdapterCB->DeferredQueue[Loopback], DeferredDesc);
+
+ NdisWanSetDeferred(AdapterCB);
+
+ NdisReleaseSpinLock(&AdapterCB->Lock);
+
+ } else {
+ NdisWanDbgOut(DBG_FAILURE, DBG_LOOPBACK, ("NdisWanQueueLoopbackPacket: Memory allocation failure!"));
+ }
+}
+
+VOID
+NdisWanProcessLoopbacks(
+ PADAPTERCB AdapterCB
+ )
+{
+ RECV_DESC RecvDesc;
+
+ NdisWanDbgOut(DBG_TRACE, DBG_LOOPBACK, ("NdisWanIndicateLoopback: Enter"));
+ NdisWanDbgOut(DBG_TRACE, DBG_LOOPBACK, ("NdisWanIndicateLoopback: AdapterCB 0x%8.8x", AdapterCB));
+
+ while (!IsDeferredQueueEmpty(&AdapterCB->DeferredQueue[Loopback])) {
+
+ PDEFERRED_DESC ReturnDesc;
+ PLOOPBACK_DESC LoopbackDesc;
+
+ ReturnDesc = RemoveHeadDeferredQueue(&AdapterCB->DeferredQueue[Loopback]);
+
+ NdisReleaseSpinLock(&AdapterCB->Lock);
+
+ LoopbackDesc = ReturnDesc->Context;
+
+ NdisWanDbgOut(DBG_INFO, DBG_LOOPBACK, ("NdisWanIndicateLoopback: Desc 0x%8.8x", LoopbackDesc));
+
+ RecvDesc.Flags = 0x4c4F4F50;
+ RecvDesc.WanHeader = LoopbackDesc->Buffer;
+ RecvDesc.WanHeaderLength = 14;
+ RecvDesc.LookAhead = NULL;
+ RecvDesc.LookAheadLength = 0;
+ RecvDesc.CurrentBuffer = LoopbackDesc->Buffer + 14;
+ RecvDesc.CurrentBufferLength = LoopbackDesc->BufferLength - 14;
+
+ ASSERT((LONG)RecvDesc.CurrentBufferLength > 0);
+
+ NdisMEthIndicateReceive(AdapterCB->hMiniportHandle,
+ &RecvDesc,
+ LoopbackDesc->Buffer,
+ 14,
+ LoopbackDesc->Buffer + 14,
+ LoopbackDesc->BufferLength - 14,
+ LoopbackDesc->BufferLength - 14);
+
+ NdisWanFreeMemory(LoopbackDesc);
+
+ NdisAcquireSpinLock(&AdapterCB->Lock);
+
+ AdapterCB->Flags |= RECEIVE_COMPLETE;
+
+ InsertHeadDeferredQueue(&AdapterCB->FreeDeferredQueue, ReturnDesc);
+ }
+}
diff --git a/private/ntos/ndis/ndiswan/memory.c b/private/ntos/ndis/ndiswan/memory.c
new file mode 100644
index 000000000..740a74e41
--- /dev/null
+++ b/private/ntos/ndis/ndiswan/memory.c
@@ -0,0 +1,1624 @@
+/*++
+
+Copyright (c) 1990-1995 Microsoft Corporation
+
+Module Name:
+
+ Ndiswan.c
+
+Abstract:
+
+ This is the initialization file for the NdisWan driver. This driver
+ is a shim between the protocols, where it conforms to the NDIS 3.1
+ Miniport interface spec, and the WAN Miniport drivers, where it exports
+ the WAN Extensions for Miniports (it looks like a protocol to the WAN
+ Miniport drivers).
+
+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
+//
+
+NDIS_STATUS
+NdisWanCreateLinkCB(
+ OUT PLINKCB *LinkCB
+ );
+
+VOID
+NdisWanInitLinkCB(
+ IN PLINKCB *LinkCB,
+ IN PWAN_ADAPTERCB WanAdapterCB,
+ IN ULONG SendWindow
+ );
+
+VOID
+NdisWanDestroyLinkCB(
+ IN PLINKCB LinkCB
+ );
+
+NDIS_STATUS
+NdisWanCreateBundleCB(
+ OUT PBUNDLECB *BundleCB
+ );
+
+VOID
+NdisWanInitBundleCB(
+ IN PBUNDLECB BundleCB
+ );
+
+VOID
+NdisWanDestroyBundleCB(
+ IN PBUNDLECB BundleCB
+ );
+
+NDIS_STATUS
+NdisWanCreateProtocolCB(
+ OUT PPROTOCOLCB *ProtocolCB,
+ IN USHORT usProtocolType,
+ IN USHORT usBindingNameLength,
+ IN PWSTR BindingName,
+ IN ULONG ulBufferLength,
+ IN PUCHAR Buffer
+ );
+
+//VOID
+//NdisWanInitProtocolCB(
+// IN PPROTOCOLCB ProtocolCB,
+// IN ULONG ulBufferLength,
+// IN PUCHAR Buffer,
+// IN USHORT usProtocolType
+// );
+
+VOID
+NdisWanDestroyProtocolCB(
+ IN PPROTOCOLCB ProtocolCB
+ );
+
+
+NDIS_STATUS
+NdisWanAllocateSendResources(
+ IN PLINKCB LinkCB,
+ IN ULONG SendWindow
+ );
+
+VOID
+NdisWanFreeSendResources(
+ IN PLINKCB LinkCB
+ );
+
+//
+// End local function prototypes
+//
+
+
+NDIS_STATUS
+NdisWanCreateAdapterCB(
+ OUT PADAPTERCB *pAdapterCB,
+ IN PNDIS_STRING AdapterName
+ )
+/*++
+
+Routine Name:
+
+ NdisWanCreateAdapterCB
+
+Routine Description:
+
+ This routine creates and initializes an AdapterCB
+
+Arguments:
+
+ pAdapterCB - Pointer to a pointer to the AdapterCB that was created
+
+Return Values:
+
+ NDIS_STATUS_SUCCESS
+ NDIS_STATUS_RESOURCES
+
+--*/
+{
+ PADAPTERCB LocalAdapterCB;
+ ULONG ulAllocationSize, i;
+ PDEFERRED_DESC FreeDesc;
+
+ NdisWanDbgOut(DBG_TRACE, DBG_MEMORY, ("NdisWanCreateAdapterCB: Enter"));
+
+ //
+ // Allocate and zero out the memory block
+ //
+ ulAllocationSize = sizeof(ADAPTERCB) + 20*sizeof(DEFERRED_DESC);
+ NdisWanAllocateMemory(&LocalAdapterCB, ulAllocationSize);
+
+ if (LocalAdapterCB == NULL) {
+
+ return (NDIS_STATUS_RESOURCES);
+ }
+
+ //
+ // setup the new control block
+ //
+ LocalAdapterCB->ulAllocationSize = ulAllocationSize;
+
+ NdisAllocateSpinLock(&LocalAdapterCB->Lock);
+
+#ifdef MINIPORT_NAME
+// NdisWanStringToNdisString(&LocalAdapterCB->AdapterName, AdapterName->Buffer);
+ NdisWanAllocateAdapterName(&LocalAdapterCB->AdapterName, AdapterName);
+#endif
+
+ //
+ // Setup free deferred desc list
+ //
+ FreeDesc = (PDEFERRED_DESC)((PUCHAR)LocalAdapterCB + sizeof(ADAPTERCB));
+
+ for (i = 0; i < 20; i++) {
+ InsertHeadDeferredQueue(&LocalAdapterCB->FreeDeferredQueue, FreeDesc);
+ (PUCHAR)FreeDesc += sizeof(DEFERRED_DESC);
+ }
+
+#if DBG
+ InitializeListHead(&LocalAdapterCB->DbgNdisPacketList);
+#endif
+
+ //
+ // Add to global list
+ //
+ InsertTailGlobalList(AdapterCBList, &(LocalAdapterCB->Linkage));
+
+ *pAdapterCB = LocalAdapterCB;
+
+ NdisWanDbgOut(DBG_TRACE, DBG_MEMORY, ("%ls AdapterCB: 0x%x, Number: %d",
+ LocalAdapterCB->AdapterName.Buffer, *pAdapterCB, AdapterCBList.ulCount));
+
+ NdisWanDbgOut(DBG_TRACE, DBG_MEMORY, ("NdisWanCreateAdapterCB: Exit"));
+
+ return (NDIS_STATUS_SUCCESS);
+}
+
+VOID
+NdisWanDestroyAdapterCB(
+ IN PADAPTERCB pAdapterCB
+ )
+/*++
+
+Routine Name:
+
+ NdisWanDestroyAdapterCB
+
+Routine Description:
+
+ This destroys an AdapterCB
+
+Arguments:
+
+ pAdapterCB - Pointer to to the AdapterCB that is being destroyed
+
+Return Values:
+
+ None
+
+--*/
+{
+ NdisWanDbgOut(DBG_TRACE, DBG_MEMORY, ("NdisWanDestroyAdapterCB: Enter"));
+ NdisWanDbgOut(DBG_TRACE, DBG_MEMORY, ("AdapterCB: 0x%x", pAdapterCB));
+
+#ifdef MINIPORT_NAME
+ NdisWanFreeNdisString(&pAdapterCB->AdapterName);
+#endif
+
+ NdisFreeSpinLock(&pAdapterCB->Lock);
+
+ NdisWanFreeMemory(pAdapterCB);
+
+ NdisWanDbgOut(DBG_TRACE, DBG_MEMORY, ("NdisWanDestroyAdapterCB: Exit"));
+}
+
+NDIS_STATUS
+NdisWanCreateWanAdapterCB(
+ IN PWSTR BindName
+ )
+/*++
+
+Routine Name:
+
+ NdisWanCreateWanAdapterCB
+
+Routine Description:
+
+ This routine creates and initializes a WanAdapterCB
+
+Arguments:
+
+ BindName - Pointer to an NDIS_STRING that has the name of the WAN Miniport
+ that will be used in the NdisOpenAdapter call when we bind to
+ the WAN Miniport.
+
+Return Values:
+
+ NDIS_STATUS_SUCCESS
+ NDIS_STATUS_RESOURCES
+
+--*/
+{
+ PWAN_ADAPTERCB pWanAdapterCB;
+ ULONG ulAllocationSize;
+
+ NdisWanDbgOut(DBG_TRACE, DBG_MEMORY, ("NdisWanCreateWanAdapterCB: Enter"));
+ NdisWanDbgOut(DBG_TRACE, DBG_MEMORY, ("BindName: %ls", BindName));
+
+ //
+ // Allocate memory for WanAdapterCB
+ //
+ ulAllocationSize = sizeof(WAN_ADAPTERCB);
+
+ NdisWanAllocateMemory(&pWanAdapterCB, ulAllocationSize);
+
+ if (pWanAdapterCB == NULL) {
+
+ return (NDIS_STATUS_RESOURCES);
+ }
+
+ //
+ // Init WanAdapterCB
+ //
+
+ //
+ // Setup new control block
+ //
+ pWanAdapterCB->ulAllocationSize = ulAllocationSize;
+
+ NdisWanStringToNdisString(&(pWanAdapterCB->MiniportName), BindName);
+
+ NdisAllocateSpinLock(&pWanAdapterCB->Lock);
+ InitializeListHead(&pWanAdapterCB->FreeLinkCBList);
+
+#if DBG
+ InitializeListHead(&pWanAdapterCB->DbgWanPacketList);
+#endif
+
+ //
+ // Put WanAdapterCB on global list
+ //
+ InsertTailGlobalList(WanAdapterCBList, &(pWanAdapterCB->Linkage));
+
+ NdisWanDbgOut(DBG_TRACE, DBG_MEMORY, ("WanMiniport %ls WanAdapterCB: 0x%x",
+ pWanAdapterCB->MiniportName.Buffer, pWanAdapterCB));
+ NdisWanDbgOut(DBG_TRACE, DBG_MEMORY, ("NdisWanCreateWanAdapterCB: Exit"));
+
+ return(NDIS_STATUS_SUCCESS);
+}
+
+VOID
+NdisWanDestroyWanAdapterCB(
+ IN PWAN_ADAPTERCB pWanAdapterCB
+ )
+/*++
+
+Routine Name:
+
+ NdisWanDestroyWanAdapterCB
+
+Routine Description:
+
+ This routine destroys a WanAdapterCB
+
+Arguments:
+
+ pWanAdapterCB - Pointer to the WanAdapterCB that is being destroyed
+
+Return Values:
+
+ None
+
+--*/
+{
+ NdisWanDbgOut(DBG_TRACE, DBG_MEMORY, ("NdisWanDestroyWanAdapterCB: Enter - WanAdapterCB: 0x%4.4x", pWanAdapterCB));
+
+ //
+ // Free the memory allocated for the NDIS_STRING
+ //
+ NdisWanFreeNdisString(&pWanAdapterCB->MiniportName);
+
+ NdisFreeSpinLock(&pWanAdapter->Lock);
+
+ //
+ // Free the memory allocated for the control block
+ //
+ NdisWanFreeMemory(pWanAdapterCB);
+
+ NdisWanDbgOut(DBG_TRACE, DBG_MEMORY, ("NdisWanDestroyWanAdapterCB: Exit"));
+}
+
+VOID
+NdisWanGetProtocolCB(
+ OUT PPROTOCOLCB *ProtocolCB,
+ IN USHORT usProtocolType,
+ IN USHORT usBindingNameLength,
+ IN PWSTR BindingName,
+ IN ULONG ulBufferLength,
+ IN PUCHAR Buffer
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ *ProtocolCB = NULL;
+
+// NdisAcquireSpinLock(&(FreeProtocolCBList.Lock));
+
+ //
+ // See if there are any ProtocolCB's available on the free list.
+ // If there are not we will need to allocate one.
+ //
+// if (FreeProtocolCBList.ulCount == 0) {
+
+ //
+ // Create ProtocolCB
+ //
+ NdisWanCreateProtocolCB(ProtocolCB,
+ usProtocolType,
+ usBindingNameLength,
+ BindingName,
+ ulBufferLength,
+ Buffer);
+
+// } else {
+
+ //
+ // Get the ProtocolCB from the free list
+ //
+// *ProtocolCB = (PPROTOCOLCB)RemoveHeadList(&(FreeProtocolCBList.List));
+
+// FreeProtocolCBList.ulCount--;
+
+// }
+
+// NdisReleaseSpinLock(&(FreeProtocolCBList.Lock));
+
+// if (*ProtocolCB != NULL) {
+// NdisWanInitProtocolCB(*ProtocolCB,
+// ulBufferLength,
+// Buffer,
+// usProtocolType);
+// }
+
+}
+
+NDIS_STATUS
+NdisWanCreateProtocolCB(
+ OUT PPROTOCOLCB *ProtocolCB,
+ IN USHORT usProtocolType,
+ IN USHORT usBindingNameLength,
+ IN PWSTR BindingName,
+ IN ULONG ulBufferLength,
+ IN PUCHAR Buffer
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+ NDIS_STATUS_SUCCESS - ProtocolCB was allocated and initialized
+ NDIS_STATUS_RESOURCES - Error allocating memory for ProtocolCB
+
+--*/
+{
+ PPROTOCOLCB LocalProtocolCB = NULL;
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+ ULONG ulAllocationSize = sizeof(PROTOCOLCB) + ulBufferLength;
+ PUCHAR AllocatedMemory;
+ ULONG i;
+
+ NdisWanAllocateMemory(&AllocatedMemory, ulAllocationSize);
+
+ if (AllocatedMemory != NULL) {
+
+ LocalProtocolCB = (PPROTOCOLCB)AllocatedMemory;
+ LocalProtocolCB->ulAllocationSize = ulAllocationSize;
+ AllocatedMemory += sizeof(PROTOCOLCB);
+ LocalProtocolCB->LineUpInfo = AllocatedMemory;
+
+#ifdef BANDWIDTH_ON_DEMAND
+ //
+ // Initialize the sample table
+ //
+ LocalProtocolCB->SampleTable.ulSampleArraySize = SAMPLE_ARRAY_SIZE;
+ NdisWanInitWanTime(&LocalProtocolCB->SampleTable.SampleRate, ONE_HUNDRED_MILS);
+ NdisWanInitWanTime(&LocalProtocolCB->SampleTable.SamplePeriod, ONE_SECOND);
+#endif
+
+ //
+ // Copy the bindingname
+ //
+ NdisWanStringToNdisString(&LocalProtocolCB->BindingName, BindingName);
+
+ //
+ // Copy over the protocol info
+ //
+ LocalProtocolCB->ulLineUpInfoLength = ulBufferLength;
+ NdisMoveMemory(LocalProtocolCB->LineUpInfo,
+ Buffer,
+ ulBufferLength);
+
+ //
+ // Setup the protocol type
+ //
+ LocalProtocolCB->usProtocolType = usProtocolType;
+
+ //
+ // Get the PPP protocol value for this protocol type
+ //
+ LocalProtocolCB->usPPPProtocolID = GetPPP_ProtocolID(usProtocolType, PROTOCOL_TYPE);
+
+ switch (usProtocolType) {
+ case PROTOCOL_IP:
+ LocalProtocolCB->NonIdleDetectFunc = IpIsDataFrame;
+ break;
+ case PROTOCOL_IPX:
+ LocalProtocolCB->NonIdleDetectFunc = IpxIsDataFrame;
+ break;
+ case PROTOCOL_NBF:
+ LocalProtocolCB->NonIdleDetectFunc = NbfIsDataFrame;
+ break;
+ default:
+ LocalProtocolCB->NonIdleDetectFunc = NULL;
+ break;
+ }
+
+ NdisWanGetSystemTime(&LocalProtocolCB->LastRecvNonIdleData);
+
+#ifdef BANDWIDTH_ON_DEMAND
+
+ LocalProtocolCB->SampleTable.ulFirstIndex =
+ LocalProtocolCB->SampleTable.ulCurrentIndex = 0;
+ NdisZeroMemory(&LocalProtocolCB->SampleTable.SampleArray[0],
+ sizeof(SEND_SAMPLE) * SAMPLE_ARRAY_SIZE);
+
+#endif // end BANDWIDTH_ON_DEMAND
+
+ } else {
+
+ Status = NDIS_STATUS_RESOURCES;
+ NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_MEMORY, ("Error allocating memory for ProtocolCB, ulAllocationSize: %d",
+ ulAllocationSize));
+ }
+
+ *ProtocolCB = LocalProtocolCB;
+
+ return (Status);
+}
+
+//VOID
+//NdisWanInitProtocolCB(
+// IN PPROTOCOLCB ProtocolCB,
+// IN ULONG ulBufferLength,
+// IN PUCHAR Buffer,
+// IN USHORT usProtocolType
+// )
+///*++
+//
+//Routine Name:
+//
+//Routine Description:
+//
+//Arguments:
+//
+//Return Values:
+//
+//--*/
+//{
+// //
+// // Copy over the protocol info
+// //
+// ProtocolCB->ulLineUpInfoLength = ulBufferLength;
+// NdisMoveMemory(ProtocolCB->LineUpInfo,
+// Buffer,
+// ulBufferLength);
+//
+// //
+// // Setup the protocol type
+// //
+// ProtocolCB->usProtocolType = usProtocolType;
+//
+// //
+// // Get the PPP protocol value for this protocol type
+// //
+// ProtocolCB->usPPPProtocolID = GetPPP_ProtocolID(usProtocolType, PROTOCOL_TYPE);
+//
+// ProtocolCB->SampleTable.ulFirstIndex =
+// ProtocolCB->SampleTable.ulCurrentIndex = 0;
+// NdisZeroMemory(&ProtocolCB->SampleTable.SampleArray[0],
+// sizeof(SEND_SAMPLE) * SAMPLE_ARRAY_SIZE);
+//
+//}
+
+VOID
+NdisWanReturnProtocolCB(
+ IN PPROTOCOLCB ProtocolCB
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+// NdisAcquireSpinLock(&(FreeProtocolCBList.Lock));
+//
+// if (FreeProtocolCBList.ulCount > FreeProtocolCBList.ulMaxCount) {
+
+ NdisWanDestroyProtocolCB(ProtocolCB);
+
+// } else {
+//
+// InsertTailGlobalList(FreeProtocolCBList, &(ProtocolCB->Linkage));
+//
+// FreeProtocolCBList.ulCount++;
+//
+// }
+//
+// NdisReleaseSpinLock(&(FreeProtocolCBList.Lock));
+}
+
+VOID
+NdisWanDestroyProtocolCB(
+ IN PPROTOCOLCB ProtocolCB
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ ASSERT(ProtocolCB->HeadNdisPacketQueue == NULL);
+ ASSERT(ProtocolCB->TailNdisPacketQueue == NULL);
+
+ if (ProtocolCB->DeviceName.Length != 0) {
+ NdisWanFreeNdisString(&ProtocolCB->DeviceName);
+ }
+
+ if (ProtocolCB->BindingName.Length != 0) {
+ NdisWanFreeNdisString(&ProtocolCB->BindingName);
+ }
+
+ NdisWanFreeMemory(ProtocolCB);
+}
+
+VOID
+NdisWanGetLinkCB(
+ OUT PLINKCB *LinkCB,
+ IN PWAN_ADAPTERCB WanAdapterCB,
+ IN ULONG SendWindow
+ )
+/*++
+
+Routine Name:
+
+ NdisWanGetLinkCB
+
+Routine Description:
+
+ This function returns a pointer to a LinkCB. The LinkCB is either retrieved
+ from the WanAdapters free list or, if this list is empty, it is allocated.
+
+Arguments:
+
+ *LinkCB - Pointer to the location to store the pointer to the LinkCB
+
+ WanAdapterCB - Pointer to the WanAdapter control block that this Link is
+ associated with
+
+Return Values:
+
+ None
+
+--*/
+{
+ //
+ // See if we have any free LinkCB's hanging around
+ // if not we will allocate one
+ //
+ NdisAcquireSpinLock(&(WanAdapterCB->Lock));
+
+ if (IsListEmpty(&(WanAdapterCB->FreeLinkCBList))) {
+
+ //
+ // Create LinkCB
+ //
+ NdisWanCreateLinkCB(LinkCB);
+
+ } else {
+
+ //
+ // Get the LinkCB from the free list
+ //
+ *LinkCB = (PLINKCB)RemoveHeadList(&(WanAdapterCB->FreeLinkCBList));
+ }
+
+ NdisReleaseSpinLock(&(WanAdapterCB->Lock));
+
+ //
+ // Set the new link state
+ //
+ NdisWanInitLinkCB(LinkCB, WanAdapterCB, SendWindow);
+}
+
+NDIS_STATUS
+NdisWanCreateLinkCB(
+ OUT PLINKCB *LinkCB
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+ PLINKCB LocalLinkCB = NULL;
+ ULONG ulAllocationSize, n;
+ PUCHAR AllocatedMemory = NULL;
+
+ //
+ // Figure out how much we need to allocate
+ //
+ ulAllocationSize = sizeof(LINKCB);
+
+ //
+ // Allocate the memory for the LinkCB and it's WAN PACKETS
+ //
+ NdisWanAllocateMemory(&AllocatedMemory, ulAllocationSize);
+
+
+ if (AllocatedMemory != NULL) {
+
+ //
+ // Initialize the control block
+ //
+ LocalLinkCB = (PLINKCB)AllocatedMemory;
+ LocalLinkCB->ulAllocationSize = ulAllocationSize;
+
+ InitializeListHead(&LocalLinkCB->WanPacketPool);
+ NdisWanInitializeSyncEvent(&LocalLinkCB->OutstandingFramesEvent);
+
+ } else {
+ Status = NDIS_STATUS_RESOURCES;
+
+ NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_MEMORY, ("Error allocating memory for LinkCB, AllocationSize: %d",
+ ulAllocationSize));
+ }
+
+ *LinkCB = LocalLinkCB;
+
+ return (Status);
+}
+
+VOID
+NdisWanInitLinkCB(
+ IN PLINKCB *LinkCB,
+ IN PWAN_ADAPTERCB WanAdapterCB,
+ IN ULONG SendWindow
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ PLINKCB LocalLinkCB = *LinkCB;
+
+ if (LocalLinkCB == NULL) {
+ return;
+ }
+
+ LocalLinkCB->hLinkContext = NULL;
+ LocalLinkCB->ulReferenceCount = 0;
+ LocalLinkCB->State = LINK_UP;
+ LocalLinkCB->WanAdapterCB = WanAdapterCB;
+ LocalLinkCB->OutstandingFrames = 0;
+ LocalLinkCB->LastRecvSeqNumber = 0;
+ LocalLinkCB->ulBandwidth = 100;
+ LocalLinkCB->PacketMemory = NULL;
+ LocalLinkCB->PacketMemorySize = 0;
+ LocalLinkCB->RecvFragmentsLost = 0;
+
+ NdisZeroMemory(&LocalLinkCB->LinkInfo, sizeof(WAN_LINK_INFO));
+
+ LocalLinkCB->LinkInfo.HeaderPadding = WanAdapterCB->WanInfo.HeaderPadding;
+ LocalLinkCB->LinkInfo.TailPadding = WanAdapterCB->WanInfo.TailPadding;
+ LocalLinkCB->LinkInfo.SendACCM =
+ LocalLinkCB->LinkInfo.RecvACCM = WanAdapterCB->WanInfo.DesiredACCM;
+
+ NdisZeroMemory(&LocalLinkCB->LinkStats, sizeof(WAN_STATS));
+
+ if (NdisWanAllocateSendResources(LocalLinkCB, SendWindow) != NDIS_STATUS_SUCCESS) {
+ //
+ // return the linkcb
+ //
+ NdisWanReturnLinkCB(LocalLinkCB);
+ *LinkCB = NULL;
+ }
+}
+
+VOID
+NdisWanReturnLinkCB(
+ PLINKCB LinkCB
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ PWAN_ADAPTERCB WanAdapterCB = LinkCB->WanAdapterCB;
+
+ NdisAcquireSpinLock(&(WanAdapterCB->Lock));
+
+ //
+ // Free the wanpacket pool
+ //
+ NdisWanFreeSendResources(LinkCB);
+
+ InsertTailList(&WanAdapterCB->FreeLinkCBList, &LinkCB->Linkage);
+
+ NdisReleaseSpinLock(&(WanAdapterCB->Lock));
+}
+
+VOID
+NdisWanDestroyLinkCB(
+ IN PLINKCB LinkCB
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ PWAN_ADAPTERCB WanAdapterCB = LinkCB->WanAdapterCB;
+
+ //
+ // Free the memory allocated for the control block
+ //
+ NdisWanFreeMemory(LinkCB);
+}
+
+NDIS_STATUS
+NdisWanAllocateSendResources(
+ IN PLINKCB LinkCB,
+ IN ULONG SendWindow
+ )
+/*++
+
+Routine Name:
+
+ NdisWanAllocateSendResources
+
+Routine Description:
+
+ Allocates all resources (SendDescriptors, WanPackets, ...)
+ required for sending data. Should be called at line up time.
+
+Arguments:
+
+ LinkCB - Pointer to the linkcb that the send resources will be attached to.
+ SendWindow - Maximum number of sends that this link can handle
+
+Return Values:
+
+ NDIS_STATUS_SUCCESS
+ NDIS_STATUS_RESOURCES
+
+--*/
+{
+ PWAN_ADAPTERCB WanAdapterCB = LinkCB->WanAdapterCB;
+ ULONG BufferSize, PacketMemorySize, NumberOfPackets, n;
+ PUCHAR PacketMemory = NULL;
+ PNDIS_WAN_PACKET WanPacket;
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+
+ SendWindow = (SendWindow == 0) ?
+ WanAdapterCB->WanInfo.MaxTransmit : SendWindow;
+
+ SendWindow = (SendWindow == 0) ? 1 : SendWindow;
+
+ //
+ // The number of packets that we will create is the send
+ // window of this WAN Miniport + 1
+ //
+ NumberOfPackets = SendWindow + 1;
+
+ //
+ // The size of the buffer that we create is
+ //
+ BufferSize = WanAdapterCB->WanInfo.MaxFrameSize +
+ WanAdapterCB->WanInfo.HeaderPadding +
+ WanAdapterCB->WanInfo.TailPadding +
+ 40 + sizeof(PVOID);
+
+ //
+ // We assume compression is always on so we pad out 12%
+ // incase the compressor expands. I don't know where the
+ // 12% figure comes from.
+ //
+ BufferSize += (WanAdapterCB->WanInfo.MaxFrameSize + 7) / 8;
+
+ //
+ // Make sure that the buffer is dword aligned.
+ //
+ BufferSize &= ~(sizeof(PVOID) - 1);
+
+ PacketMemorySize = (BufferSize + sizeof(NDIS_WAN_PACKET)) * NumberOfPackets;
+
+ //
+ // Allocate the memory for the wan packet buffer pool
+ //
+ NdisAllocateMemory(&PacketMemory,
+ PacketMemorySize,
+ WanAdapterCB->WanInfo.MemoryFlags,
+ WanAdapterCB->WanInfo.HighestAcceptableAddress);
+
+ if (PacketMemory != NULL) {
+
+ LinkCB->PacketMemory = PacketMemory;
+ LinkCB->PacketMemorySize = PacketMemorySize;
+ LinkCB->BufferSize = BufferSize;
+
+ for (n = 0; n < NumberOfPackets; n++) {
+
+ WanPacket = (PNDIS_WAN_PACKET)PacketMemory;
+ PacketMemory += sizeof(NDIS_WAN_PACKET);
+
+ InsertTailList(&LinkCB->WanPacketPool, &WanPacket->WanPacketQueue);
+ LinkCB->ulWanPacketCount++;
+ }
+
+ //
+ // Walk the list of newly created packets and fix up startbuffer and
+ // endbuffer pointers.
+ //
+ for (WanPacket = (PNDIS_WAN_PACKET)LinkCB->WanPacketPool.Flink;
+ (PVOID)WanPacket != (PVOID)&LinkCB->WanPacketPool;
+ WanPacket = (PNDIS_WAN_PACKET)WanPacket->WanPacketQueue.Flink) {
+
+ //
+ // Point to the begining of the data.
+ //
+ WanPacket->StartBuffer = PacketMemory;
+ PacketMemory += BufferSize;
+
+ //
+ // The 5 bytes give us a short buffer at the end and will
+ // keep a WAN Miniport from alignment checking if it uses
+ // this pointer to 'back copy'
+ //
+ WanPacket->EndBuffer = PacketMemory - 5;
+ }
+
+ } else {
+ Status = NDIS_STATUS_RESOURCES;
+
+ NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_MEMORY, ("Error allocating memory for BufferPool, AllocationSize: %d",
+ PacketMemorySize));
+ }
+
+ return (Status);
+}
+
+VOID
+NdisWanFreeSendResources(
+ IN PLINKCB LinkCB
+ )
+/*++
+
+Routine Name:
+
+ NdisWanFreeSendResources
+
+Routine Description:
+
+ This routine removes the WanPackets from this linkcb's send list
+ and free's the memory allocated for these packets. Should be called
+ at linedown time after all outstanding sends have been accounted for.
+
+Arguments:
+
+ LinkCB - Pointer to the linkcb that the resources are being freed from.
+
+Return Values:
+
+ None
+
+--*/
+{
+ PNDIS_WAN_PACKET WanPacket;
+ PUCHAR PacketMemory;
+ ULONG PacketMemorySize, Flags;
+
+ PacketMemory = LinkCB->PacketMemory;
+ PacketMemorySize = LinkCB->PacketMemorySize;
+ Flags = LinkCB->WanAdapterCB->WanInfo.MemoryFlags;
+
+ //
+ // Remove the packets from the wan packet pool
+ //
+ while (!IsListEmpty(&LinkCB->WanPacketPool)) {
+ RemoveHeadList(&LinkCB->WanPacketPool);
+ LinkCB->ulWanPacketCount--;
+ }
+
+ //
+ // Free the block of memory allocated for this send
+ //
+ if (PacketMemory != NULL) {
+ NdisFreeMemory(PacketMemory, PacketMemorySize, Flags);
+ }
+}
+
+VOID
+NdisWanGetBundleCB(
+ OUT PBUNDLECB *BundleCB
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ NdisAcquireSpinLock(&(FreeBundleCBList.Lock));
+
+ //
+ // See if there are any BundleCB's available on the free list.
+ // If there are not we will need to allocate one.
+ //
+ if (FreeBundleCBList.ulCount == 0) {
+
+ //
+ // Create BundleCB
+ //
+ NdisWanCreateBundleCB(BundleCB);
+
+ } else {
+
+ //
+ // Get the BundleCB from the free list
+ //
+ *BundleCB = (PBUNDLECB)RemoveHeadList(&(FreeBundleCBList.List));
+
+ FreeBundleCBList.ulCount--;
+
+ }
+
+ NdisReleaseSpinLock(&(FreeBundleCBList.Lock));
+
+ if (*BundleCB != NULL) {
+ NdisWanInitBundleCB(*BundleCB);
+ }
+}
+
+NDIS_STATUS
+NdisWanCreateBundleCB(
+ OUT PBUNDLECB *BundleCB
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+ PBUNDLECB LocalBundleCB = NULL;
+ ULONG ulAllocationSize;
+ PUCHAR AllocatedMemory = NULL;
+
+ //
+ // Allocation size is the size of the control block plus the size
+ // of a table of pointers to protocolcb's that might be routed to
+ // this bundle.
+ //
+ ulAllocationSize = sizeof(BUNDLECB) +
+ sizeof(PROTOCOLCB) +
+ (sizeof(PPROTOCOLCB) * MAX_PROTOCOLS);
+
+ NdisWanAllocateMemory(&AllocatedMemory, ulAllocationSize);
+
+ if (AllocatedMemory != NULL) {
+ PWSTR IOName = L"I/O ProtocolCB";
+ PPROTOCOLCB ProtocolCB;
+
+ //
+ // This is the bundlecb
+ //
+ LocalBundleCB = (PBUNDLECB)AllocatedMemory;
+ LocalBundleCB->ulAllocationSize = ulAllocationSize;
+ AllocatedMemory += sizeof(BUNDLECB);
+
+ //
+ // This is the memory used for the I/O protocolcb
+ //
+ ProtocolCB = (PPROTOCOLCB)AllocatedMemory;
+ AllocatedMemory += sizeof(PROTOCOLCB);
+
+ //
+ // This is the protocolcb table
+ //
+ (PUCHAR)LocalBundleCB->ProtocolCBTable = (PUCHAR)AllocatedMemory;
+
+ //
+ // Initialize the BundleCB
+ //
+
+ NdisAllocateSpinLock(&LocalBundleCB->Lock);
+ InitializeListHead(&LocalBundleCB->LinkCBList);
+ InitializeListHead(&LocalBundleCB->SendPacketQueue);
+ InitializeListHead(&LocalBundleCB->RecvDescPool);
+ InitializeListHead(&LocalBundleCB->RecvDescAssemblyList);
+ InitializeListHead(&LocalBundleCB->ProtocolCBList);
+ NdisWanInitializeSyncEvent(&LocalBundleCB->OutstandingFramesEvent);
+ NdisWanInitializeSyncEvent(&LocalBundleCB->IndicationEvent);
+
+#ifdef BANDWIDTH_ON_DEMAND
+ LocalBundleCB->UpperBonDInfo.SampleTable.ulSampleArraySize = SAMPLE_ARRAY_SIZE;
+ LocalBundleCB->LowerBonDInfo.SampleTable.ulSampleArraySize = SAMPLE_ARRAY_SIZE;
+#endif // end of BANDWIDTH_ON_DEMAND
+
+ //
+ // Add the protocolcb to the bundle's table and list
+ //
+ ProtocolCB->hProtocolHandle = 0;
+ ProtocolCB->BundleCB = LocalBundleCB;
+ ProtocolCB->HeadNdisPacketQueue =
+ ProtocolCB->TailNdisPacketQueue = NULL;
+ NdisWanStringToNdisString(&ProtocolCB->DeviceName, IOName);
+
+#ifdef BANDWIDTH_ON_DEMAND
+ ProtocolCB->SampleTable.ulSampleArraySize = SAMPLE_ARRAY_SIZE;
+ NdisWanInitWanTime(&ProtocolCB->SampleTable.SampleRate, ONE_HUNDRED_MILS);
+ NdisWanInitWanTime(&ProtocolCB->SampleTable.SamplePeriod, ONE_SECOND);
+#endif
+
+ LocalBundleCB->ProtocolCBTable[0] = ProtocolCB;
+ InsertHeadList(&LocalBundleCB->ProtocolCBList, &ProtocolCB->Linkage);
+ LocalBundleCB->ulNumberOfRoutes = 1;
+
+ } else {
+
+ Status = NDIS_STATUS_RESOURCES;
+ NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_MEMORY, ("Error allocating memory for BundleCB, AllocationSize: %d",
+ ulAllocationSize));
+ }
+
+ *BundleCB = LocalBundleCB;
+
+ return (Status);
+}
+
+VOID
+NdisWanInitBundleCB(
+ PBUNDLECB BundleCB
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ PPROTOCOLCB ProtocolCB = BundleCB->ProtocolCBTable[0];
+ PRECV_DESC RecvDescHole;
+
+#ifdef BANDWIDTH_ON_DEMAND
+ PSAMPLE_TABLE SampleTable;
+ PBOND_INFO BonDInfo;
+#endif // end of BANDWIDTH_ON_DEMAND
+
+ BundleCB->State = BUNDLE_UP;
+ NdisZeroMemory(&BundleCB->FramingInfo, sizeof(BUNDLE_FRAME_INFO));
+ BundleCB->NextLinkToXmit = NULL;
+ BundleCB->SendingLinks = 0;
+ BundleCB->SendSeqNumber = 0;
+ BundleCB->SendSeqMask = 0;
+ BundleCB->SendSeqTest = 0;
+ BundleCB->Flags = 0;
+ NdisZeroMemory(&BundleCB->LineUpInfo, sizeof(BUNDLE_LINE_UP));
+ BundleCB->LineUpInfo.ulMaximumTotalSize = MAX_TOTAL_SIZE;
+
+ //
+ // Init the recv hole desc
+ //
+ BundleCB->RecvSeqMask = 0;
+ BundleCB->RecvSeqTest = 0;
+ BundleCB->RecvFragmentsLost = 0;
+ BundleCB->MinReceivedSeqNumber = 0;
+ ASSERT(BundleCB->RecvDescAssemblyList.Flink == BundleCB->RecvDescAssemblyList.Blink);
+ NdisWanGetRecvDesc(BundleCB, &RecvDescHole);
+ RecvDescHole->SequenceNumber = 0;
+ RecvDescHole->Flags = 1;
+ BundleCB->RecvDescHole = RecvDescHole;
+ InsertHeadList(&BundleCB->RecvDescAssemblyList, &RecvDescHole->Linkage);
+ NdisWanGetSystemTime(&BundleCB->LastRecvNonIdleData);
+
+ ProtocolCB->SendMaskBit = IO_SEND_MASK_BIT;
+
+ NdisZeroMemory(&BundleCB->SendVJInfo, sizeof(VJ_INFO));
+ NdisZeroMemory(&BundleCB->RecvVJInfo, sizeof(VJ_INFO));
+ NdisZeroMemory(&BundleCB->SendCompInfo, sizeof(COMPRESS_INFO));
+ NdisZeroMemory(&BundleCB->RecvCompInfo, sizeof(COMPRESS_INFO));
+ NdisZeroMemory(&BundleCB->SendEncryptInfo,sizeof(ENCRYPTION_INFO));
+ NdisZeroMemory(&BundleCB->RecvEncryptInfo,sizeof(ENCRYPTION_INFO));
+
+/*
+#ifdef ENCRYPT_128BIT
+ BundleCB->SendEncryptInfo.SessionKeyLength =
+ BundleCB->RecvEncryptInfo.SessionKeyLength = 16;
+ BundleCB->SendCompInfo.MSCompType =
+ BundleCB->RecvCompInfo.MSCompType = NDISWAN_ENCRYPTION |
+ NDISWAN_40_ENCRYPTION |
+ NDISWAN_128_ENCRYPTION |
+ NDISWAN_COMPRESSION;
+#else
+ BundleCB->SendEncryptInfo.SessionKeyLength =
+ BundleCB->RecvEncryptInfo.SessionKeyLength = 8;
+ BundleCB->SendCompInfo.MSCompType =
+ BundleCB->RecvCompInfo.MSCompType = NDISWAN_ENCRYPTION |
+ NDISWAN_40_ENCRYPTION |
+ NDISWAN_COMPRESSION;
+#endif
+*/
+ BundleCB->SendCompInfo.CompType =
+ BundleCB->RecvCompInfo.CompType = COMPTYPE_NONE;
+
+ ProtocolCB->usProtocolType = PROTOCOL_PRIVATE_IO;
+ ProtocolCB->usPPPProtocolID = PPP_PROTOCOL_PRIVATE_IO;
+
+ BundleCB->SendMask = IO_SEND_MASK_BIT;
+
+#ifdef BANDWIDTH_ON_DEMAND
+
+ ProtocolCB->usPriority = 100;
+ ProtocolCB->ulByteQuota = 0xFFFFFFFF;
+ ProtocolCB->SampleTable.ulFirstIndex =
+ ProtocolCB->SampleTable.ulCurrentIndex = 0;
+ NdisZeroMemory(&ProtocolCB->SampleTable.SampleArray[0],
+ sizeof(SEND_SAMPLE) * SAMPLE_ARRAY_SIZE);
+
+
+ BonDInfo = &BundleCB->UpperBonDInfo;
+ BonDInfo->ulBytesThreshold = 0;
+ BonDInfo->State = BonDIdle;
+ BonDInfo->usPercentBandwidth = 0xFFFF;
+ BonDInfo->ulSecondsInSamplePeriod = 0;
+ NdisWanInitWanTime(&BonDInfo->StartTime, 0);
+
+ SampleTable = &BonDInfo->SampleTable;
+ NdisWanInitWanTime(&SampleTable->SampleRate, 0);
+ NdisWanInitWanTime(&SampleTable->SamplePeriod, 0);
+ SampleTable->ulFirstIndex =
+ SampleTable->ulCurrentIndex =
+ SampleTable->ulCurrentSampleByteCount = 0;
+
+ NdisZeroMemory(&SampleTable->SampleArray[0],
+ sizeof(SEND_SAMPLE) * SAMPLE_ARRAY_SIZE);
+
+ BonDInfo = &BundleCB->LowerBonDInfo;
+ BonDInfo->ulBytesThreshold = 0;
+ BonDInfo->State = BonDIdle;
+ BonDInfo->usPercentBandwidth = 0xFFFF;
+ BonDInfo->ulSecondsInSamplePeriod = 0;
+ NdisWanInitWanTime(&BonDInfo->StartTime, 0);
+ SampleTable = &BonDInfo->SampleTable;
+ NdisWanInitWanTime(&SampleTable->SampleRate, 0);
+ NdisWanInitWanTime(&SampleTable->SamplePeriod, 0);
+ SampleTable->ulFirstIndex =
+ SampleTable->ulCurrentIndex =
+ SampleTable->ulCurrentSampleByteCount = 0;
+
+ NdisZeroMemory(&SampleTable->SampleArray[0],
+ sizeof(SEND_SAMPLE) * SAMPLE_ARRAY_SIZE);
+
+#endif // end of BANDWIDTH_ON_DEMAND
+
+ BundleCB->ulNameLength = 0;
+ NdisZeroMemory(&BundleCB->Name, MAX_NAME_LENGTH);
+
+ NdisZeroMemory(&BundleCB->BundleStats, sizeof(WAN_STATS));
+}
+
+VOID
+NdisWanReturnBundleCB(
+ IN PBUNDLECB BundleCB
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+
+ sl_compress_terminate(&BundleCB->VJCompress);
+
+ WanDeallocateCCP(BundleCB);
+
+ FlushRecvDescAssemblyList(BundleCB);
+
+ FreeRecvDescFreeList(BundleCB);
+
+ NdisAcquireSpinLock(&(FreeBundleCBList.Lock));
+
+ if (FreeBundleCBList.ulCount >= FreeBundleCBList.ulMaxCount) {
+
+ NdisWanDestroyBundleCB(BundleCB);
+
+ } else {
+ InsertTailList(&FreeBundleCBList.List, &(BundleCB->Linkage));
+
+ FreeBundleCBList.ulCount++;
+ }
+
+ NdisReleaseSpinLock(&(FreeBundleCBList.Lock));
+}
+
+VOID
+NdisWanDestroyBundleCB(
+ IN PBUNDLECB BundleCB
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ PPROTOCOLCB ProtocolCB = BundleCB->ProtocolCBTable[0];
+
+ NdisFreeSpinLock(&BundleCB->Lock);
+
+ NdisWanFreeNdisString(&ProtocolCB->DeviceName);
+
+ NdisWanFreeMemory(BundleCB);
+}
+
+
+NDIS_STATUS
+NdisWanCreatePPPProtocolTable(
+ VOID
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+ ULONG ulAllocationSize = 0;
+ PUCHAR AllocatedMemory;
+
+
+ //
+ // Allocate ProtocolLookupTable. This table is used to match protocol values
+ // with their corresponding PPP Protocol values. The table size is set to
+ // MAX_PROTOCOLS.
+ //
+ ulAllocationSize = sizeof(PPP_PROTOCOL_TABLE) +
+ (sizeof(USHORT) * MAX_PROTOCOLS) +
+ (sizeof(USHORT) * MAX_PROTOCOLS);
+
+ NdisWanAllocateMemory(&AllocatedMemory, ulAllocationSize);
+
+ if (AllocatedMemory == NULL) {
+ NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_MEMORY,
+ ("Failed allocating memory for ProtocolLookupTable! TableSize: %d",
+ ulAllocationSize));
+
+ return (NDIS_STATUS_RESOURCES);
+ }
+
+ PPP_ProtocolTable = (PPPP_PROTOCOL_TABLE)AllocatedMemory;
+
+ //
+ // Save the allocation size
+ //
+ PPP_ProtocolTable->ulAllocationSize = ulAllocationSize;
+
+ //
+ // Store the array size. This should be read from the registry
+ //
+ PPP_ProtocolTable->ulArraySize = MAX_PROTOCOLS;
+
+ NdisAllocateSpinLock(&PPP_ProtocolTable->Lock);
+
+ //
+ // Setup the pointer to the ProtocolValue array
+ //
+ AllocatedMemory += sizeof(PPP_PROTOCOL_TABLE);
+ PPP_ProtocolTable->ProtocolID = (PUSHORT)(AllocatedMemory);
+
+ //
+ // Setup the pointer to the PPPProtocolValue array
+ //
+ AllocatedMemory += (sizeof(USHORT) * MAX_PROTOCOLS);
+ PPP_ProtocolTable->PPPProtocolID = (PUSHORT)(AllocatedMemory);
+
+ //
+ // Insert default values for Netbuei, IP, IPX
+ //
+ InsertPPP_ProtocolID(PROTOCOL_PRIVATE_IO, PROTOCOL_TYPE);
+ InsertPPP_ProtocolID(PPP_PROTOCOL_PRIVATE_IO, PPP_TYPE);
+
+ InsertPPP_ProtocolID(PROTOCOL_IP, PROTOCOL_TYPE);
+ InsertPPP_ProtocolID(PPP_PROTOCOL_IP, PPP_TYPE);
+
+ InsertPPP_ProtocolID(PROTOCOL_IPX, PROTOCOL_TYPE);
+ InsertPPP_ProtocolID(PPP_PROTOCOL_IPX, PPP_TYPE);
+
+ InsertPPP_ProtocolID(PROTOCOL_NBF, PROTOCOL_TYPE);
+ InsertPPP_ProtocolID(PPP_PROTOCOL_NBF, PPP_TYPE);
+
+ return (Status);
+
+}
+
+VOID
+NdisWanDestroyPPPProtocolTable(
+ VOID
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ NdisFreeSpinLock(&PPP_ProtocolTable->Lock);
+
+ NdisWanFreeMemory(PPP_ProtocolTable);
+}
+
+NDIS_STATUS
+NdisWanCreateConnectionTable(
+ ULONG TableSize
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+ ULONG ulAllocationSize = 0;
+ PUCHAR AllocatedMemory;
+ PCONNECTION_TABLE NewTable;
+
+ //
+ // Since we skip the first place in the tables we increase the
+ // size by one.
+ //
+ TableSize += 1;
+
+ //
+ // Allocate the Bundle and Link Arrays based on the number of possible connections
+ // that we have in the system. This should be grown if we get called
+ // to reinitialize and gain new ports.
+ //
+ ulAllocationSize = sizeof(CONNECTION_TABLE) +
+ (sizeof(PBUNDLECB) * TableSize) +
+ (sizeof(PLINKCB) * TableSize);
+
+ NdisWanAllocateMemory(&AllocatedMemory, ulAllocationSize);
+
+ if (AllocatedMemory == NULL) {
+
+ NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_MEMORY,
+ ("Failed allocating memory for ConnectionTable! Size: %d, Links: %d",
+ ulAllocationSize, TableSize));
+
+ return (NDIS_STATUS_RESOURCES);
+ }
+
+ NewTable = (PCONNECTION_TABLE)AllocatedMemory;
+
+ NdisAllocateSpinLock(&NewTable->Lock);
+
+ //
+ // This is the amount of memory we allocated
+ //
+ NewTable->ulAllocationSize = ulAllocationSize;
+ NewTable->ulArraySize = TableSize;
+ InitializeListHead(&NewTable->BundleList);
+
+ //
+ // Setup pointer to the linkcb array
+ //
+ AllocatedMemory += sizeof(CONNECTION_TABLE);
+ NewTable->LinkArray = (PLINKCB*)(AllocatedMemory);
+
+ //
+ // Setup the pointer to the bundlecb array
+ //
+ AllocatedMemory += (sizeof(PLINKCB) * TableSize);
+ NewTable->BundleArray = (PBUNDLECB*)(AllocatedMemory);
+
+ if (ConnectionTable != NULL) {
+ //
+ // We must be growing the table
+ //
+ NewTable->ulNumActiveLinks = ConnectionTable->ulNumActiveLinks;
+ NewTable->ulNumActiveBundles = ConnectionTable->ulNumActiveBundles;
+
+ NdisMoveMemory((PUCHAR)NewTable->LinkArray,
+ (PUCHAR)ConnectionTable->LinkArray,
+ ConnectionTable->ulArraySize * sizeof(PLINKCB));
+
+ NdisMoveMemory((PUCHAR)NewTable->BundleArray,
+ (PUCHAR)ConnectionTable->BundleArray,
+ ConnectionTable->ulArraySize * sizeof(PBUNDLECB));
+
+ while (!IsListEmpty(&ConnectionTable->BundleList)) {
+ PBUNDLECB BundleCB;
+
+ BundleCB = (PBUNDLECB)RemoveHeadList(&ConnectionTable->BundleList);
+ InsertTailList(&NewTable->BundleList, &BundleCB->Linkage);
+ }
+
+ NdisWanDestroyConnectionTable();
+ }
+
+ ConnectionTable = NewTable;
+
+ return (Status);
+}
+
+VOID
+NdisWanDestroyConnectionTable(
+ VOID
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ NdisFreeSpinLock(&ConnectionTable->Lock);
+
+ NdisWanFreeMemory(ConnectionTable);
+}
+
+VOID
+NdisWanGetDeferredDesc(
+ PADAPTERCB AdapterCB,
+ PDEFERRED_DESC *RetDesc
+ )
+{
+ ULONG i;
+
+ if (IsDeferredQueueEmpty(&AdapterCB->FreeDeferredQueue)) {
+ PDEFERRED_DESC DeferredDesc;
+ NdisWanAllocateMemory(&DeferredDesc, sizeof(DEFERRED_DESC) * 20);
+
+ if (DeferredDesc != NULL) {
+ for (i = 0; i < 20; i++) {
+ InsertHeadDeferredQueue(&AdapterCB->FreeDeferredQueue, DeferredDesc);
+ (PUCHAR)DeferredDesc += sizeof(DEFERRED_DESC);
+ }
+ }
+ }
+
+ *RetDesc = RemoveHeadDeferredQueue(&AdapterCB->FreeDeferredQueue);
+
+ ASSERT(*RetDesc != NULL);
+}
diff --git a/private/ntos/ndis/ndiswan/miniport.c b/private/ntos/ndis/ndiswan/miniport.c
new file mode 100644
index 000000000..ed5213a25
--- /dev/null
+++ b/private/ntos/ndis/ndiswan/miniport.c
@@ -0,0 +1,576 @@
+/*++
+
+Copyright (c) 1990-1995 Microsoft Corporation
+
+Module Name:
+
+ Miniport.c
+
+Abstract:
+
+ This file contains the procedures that makeup most of the NDIS 3.1
+ Miniport interface.
+
+
+Author:
+
+ Tony Bell (TonyBe) June 06, 1995
+
+Environment:
+
+ Kernel Mode
+
+Revision History:
+
+ TonyBe 06/06/95 Created
+
+--*/
+
+#include "wan.h"
+
+//
+// Local function prototypes
+//
+#ifndef USE_NDIS_MINIPORT_CALLBACK
+VOID
+DeferredTimerFunction(
+ PVOID System1,
+ PADAPTERCB AdapterCB,
+ PVOID System2,
+ PVOID System3
+ );
+#endif // end of !USE_NDIS_MINIPORT_CALLBACK
+
+//
+// End local function prototypes
+//
+
+BOOLEAN
+NdisWanCheckForHang(
+ IN NDIS_HANDLE MiniportAdapterContext
+ )
+/*++
+
+Routine Name:
+
+ NdisWanCheckForHang
+
+Routine Description:
+
+ This routine checks to see is this adapter needs to be reset, and if it
+ does the return value is set to TRUE. I can't think of any reason that
+ we might use this right now, but I'm sure that there will be.
+
+Arguments:
+
+ MiniportAdapterContext - AdapterContext that is given to the wrapper in
+ NdisMSetAttributes call. Is our AdapterCB.
+
+Return Values:
+
+ TRUE - Reset Adapter
+ FALSE - Don't reset adapter
+
+--*/
+{
+ PADAPTERCB AdapterCB = (PADAPTERCB)MiniportAdapterContext;
+ BOOLEAN Status = FALSE;
+
+ NdisWanInterlockedInc(&AdapterCB->ulReferenceCount);
+
+ //
+ // Does this adapter need to be reset?
+ //
+ if (AdapterCB->Flags & ASK_FOR_RESET) {
+ Status = TRUE;
+ }
+
+ NdisWanInterlockedDec(&AdapterCB->ulReferenceCount);
+ return (Status);
+}
+
+VOID
+NdisWanHalt(
+ IN NDIS_HANDLE MiniportAdapterContext
+ )
+/*++
+
+Routine Name:
+
+ NdisWanHalt
+
+Routine Description:
+
+ This routine free's all resources for the adapter.
+
+Arguments:
+
+ MiniportAdapterContext - AdapterContext that is given to the wrapper in
+ NdisMSetAttributes call. Is our AdapterCB.
+
+Return Values:
+
+ None
+
+--*/
+{
+ PADAPTERCB AdapterCB = (PADAPTERCB)MiniportAdapterContext;
+
+ NdisWanDbgOut(DBG_TRACE, DBG_MINIPORT, ("NdisWanHalt: Enter"));
+ NdisWanDbgOut(DBG_TRACE, DBG_MINIPORT, ("AdapterCB: 0x%x", AdapterCB));
+
+ NdisWanDbgOut(DBG_TRACE, DBG_MINIPORT, ("NdisWanHalt: Exit"));
+}
+
+NDIS_STATUS
+NdisWanInitialize(
+ OUT PNDIS_STATUS OpenErrorStatus,
+ OUT PUINT SelectedMediumIndex,
+ IN PNDIS_MEDIUM MediumArray,
+ IN UINT MediumArraySize,
+ IN NDIS_HANDLE MiniportAdapterHandle,
+ IN NDIS_HANDLE WrapperConfigurationContext
+ )
+/*++
+
+Routine Name:
+
+ NdisWanInitialize
+
+Routine Description:
+
+ This routine is called after NdisWan registers itself as a Miniport driver.
+ It is responsible for installing NdisWan as a Miniport driver, creating
+ adapter control blocks for each adapter NdisWan exposes (should only be 1),
+ and initializing all adapter specific variables
+
+
+Arguments:
+
+ OpenErrorStatus - Returns information about the error if this function
+ returns NDIS_STATUS_OPEN_ERROR. Used for TokenRing.
+
+ SelectedMediumIndex - An index into the MediumArray that specifies the
+ medium type of this driver. Should be WAN or 802.3
+
+ MediumArray - An array of medium types supported by the NDIS library
+
+ MediumArraySize - Size of the medium array
+
+ MiniportAdapterHandle - Handle assigned by the NDIS library that defines
+ this miniport driver. Used as handle in subsequent
+ calls to the NDIS library.
+
+ WrapperConfigurationContext - Handle used to read configuration information
+ from the registry
+
+Return Values:
+
+ NDIS_STATUS_ADAPTER_NOT_FOUND
+ NDIS_STATUS_FAILURE
+ NDIS_STATUS_NOT_ACCEPTED
+ NDIS_STATUS_OPEN_ERROR
+ NDIS_STATUS_RESOURCES
+ NDIS_STATUS_UNSUPPORTED_MEDIA
+
+--*/
+{
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+ PADAPTERCB AdapterCB;
+ UINT Index;
+ NDIS_HANDLE ConfigHandle;
+ ULONG NetworkAddressLength;
+#ifdef NT
+ LARGE_INTEGER TickCount, SystemTime;
+#endif
+
+ NdisWanDbgOut(DBG_TRACE, DBG_MINIPORT, ("NdisWanInitialize: Enter"));
+
+
+ //
+ // We have to be type 802.3 to the ndis wrapper, but the
+ // wrapper will expose us to the transports as type wan.
+ //
+ for (Index = 0; Index < MediumArraySize; Index++) {
+
+ if (MediumArray[Index] == NdisMedium802_3) {
+ break;
+ }
+ }
+
+ //
+ // We don't have a match so we are screwed
+ //
+ if (Index == MediumArraySize) {
+ return (NDIS_STATUS_UNSUPPORTED_MEDIA);
+ }
+
+ *SelectedMediumIndex = Index;
+
+ //
+ // Allocate and initialize miniport adapter structure
+ //
+#ifdef MINIPORT_NAME
+ Status = NdisWanCreateAdapterCB(&AdapterCB, &((PNDIS_MINIPORT_BLOCK)(MiniportAdapterHandle))->MiniportName);
+#else
+ Status = NdisWanCreateAdapterCB(&AdapterCB, NULL);
+#endif
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+ NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_MINIPORT,
+ ("Error Creating AdapterCB! Status: 0x%x - %s",
+ Status, NdisWanGetNdisStatus(Status)));
+ return (NDIS_STATUS_FAILURE);
+ }
+
+ NdisMSetAttributesEx(MiniportAdapterHandle,
+ AdapterCB,
+ (UINT)-1,
+ NDIS_ATTRIBUTE_IGNORE_PACKET_TIMEOUT |
+ NDIS_ATTRIBUTE_IGNORE_REQUEST_TIMEOUT,
+ NdisInterfaceInternal);
+
+ AdapterCB->MediumType = MediumArray[Index];
+ AdapterCB->ulReferenceCount = 0;
+ AdapterCB->hMiniportHandle = MiniportAdapterHandle;
+
+ NdisOpenConfiguration(&Status,
+ &ConfigHandle,
+ WrapperConfigurationContext);
+
+ if (Status == NDIS_STATUS_SUCCESS) {
+
+ NdisReadNetworkAddress(&Status,
+ (PVOID*)&(AdapterCB->NetworkAddress),
+ &NetworkAddressLength,
+ ConfigHandle);
+
+ NdisCloseConfiguration(ConfigHandle);
+
+ if (Status != NDIS_STATUS_SUCCESS ||
+ NetworkAddressLength != ETH_LENGTH_OF_ADDRESS) {
+
+ goto BuildAddress;
+
+ }
+
+
+ } else {
+
+BuildAddress:
+
+#ifdef NT
+
+ KeQueryTickCount(&TickCount);
+ KeQuerySystemTime(&SystemTime);
+
+ AdapterCB->NetworkAddress[0] = (UCHAR)((TickCount.LowPart >> 16) ^
+ (SystemTime.LowPart >> 16)) &
+ 0xFE;
+
+ AdapterCB->NetworkAddress[1] = (UCHAR)((TickCount.LowPart >> 8) ^
+ (SystemTime.LowPart >> 8));
+
+ AdapterCB->NetworkAddress[2] = (UCHAR)(TickCount.LowPart ^
+ SystemTime.LowPart);
+
+ //
+ // The following three bytes will be filled in at lineup time
+ //
+ AdapterCB->NetworkAddress[3] = 0x00;
+ AdapterCB->NetworkAddress[4] = 0x00;
+ AdapterCB->NetworkAddress[5] = 0x00;
+#endif
+
+ }
+
+#ifndef USE_NDIS_MINIPORT_CALLBACK
+ NdisMInitializeTimer(&AdapterCB->DeferredTimer,
+ AdapterCB->hMiniportHandle,
+ DeferredTimerFunction,
+ AdapterCB);
+#endif // end of !USE_NDIS_MINIPORT_CALLBACK
+
+ NdisWanDbgOut(DBG_TRACE, DBG_MINIPORT, ("NdisWanInitialize: Exit"));
+
+ return (NDIS_STATUS_SUCCESS);
+}
+
+NDIS_STATUS
+NdisWanQueryInformation(
+ IN NDIS_HANDLE MiniportAdapterContext,
+ IN NDIS_OID Oid,
+ IN PVOID InformationBuffer,
+ IN ULONG InformationBufferLength,
+ OUT PULONG BytesWritten,
+ OUT PULONG BytesNeeded
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+ PADAPTERCB AdapterCB = (PADAPTERCB)MiniportAdapterContext;
+
+ NdisWanDbgOut(DBG_TRACE, DBG_MINIPORT, ("NdisWanQueryInformation: Enter Oid: 0x%4.4x", Oid));
+
+ NdisWanInterlockedInc(&AdapterCB->ulReferenceCount);
+
+ Status = NdisWanOidProc(AdapterCB,
+ Oid,
+ QUERY_OID,
+ InformationBuffer,
+ InformationBufferLength,
+ BytesWritten,
+ BytesNeeded);
+
+ NdisWanDbgOut(DBG_TRACE, DBG_MINIPORT, ("NdisWanQueryInformation: Exit"));
+
+ NdisWanInterlockedDec(&AdapterCB->ulReferenceCount);
+
+ return (Status);
+}
+
+NDIS_STATUS
+NdisWanReconfigure(
+ OUT PNDIS_STATUS OpenErrorStatus,
+ IN NDIS_HANDLE MiniportAdapterContext,
+ IN NDIS_HANDLE WrapperConfigurationContext
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+ PADAPTERCB AdapterCB = (PADAPTERCB)MiniportAdapterContext;
+
+ NdisWanDbgOut(DBG_TRACE, DBG_MINIPORT, ("NdisWanReconfigure: Enter"));
+
+ NdisWanInterlockedInc(&AdapterCB->ulReferenceCount);
+
+ NdisWanInterlockedDec(&AdapterCB->ulReferenceCount);
+
+ NdisWanDbgOut(DBG_TRACE, DBG_MINIPORT, ("NdisWanReconfigure: Exit"));
+ return (Status);
+}
+
+NDIS_STATUS
+NdisWanReset(
+ OUT PBOOLEAN AddressingReset,
+ IN NDIS_HANDLE MiniportAdapterContext
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+ PADAPTERCB AdapterCB = (PADAPTERCB)MiniportAdapterContext;
+
+ NdisWanDbgOut(DBG_TRACE, DBG_MINIPORT, ("NdisWanReset: Enter"));
+ DbgPrint("NDISWAN: Resest for Adapter: 0x%8.8x\n", AdapterCB);
+
+ NdisWanInterlockedInc(&AdapterCB->ulReferenceCount);
+
+ AdapterCB->Flags &= ~ASK_FOR_RESET;
+
+ NdisWanInterlockedDec(&AdapterCB->ulReferenceCount);
+
+ NdisWanDbgOut(DBG_TRACE, DBG_MINIPORT, ("NdisWanReset: Exit"));
+
+ return (Status);
+}
+
+
+NDIS_STATUS
+NdisWanSetInformation(
+ IN NDIS_HANDLE MiniportAdapterContext,
+ IN NDIS_OID Oid,
+ IN PVOID InformationBuffer,
+ IN ULONG InformationBufferLength,
+ OUT PULONG BytesWritten,
+ OUT PULONG BytesNeeded
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+ PADAPTERCB AdapterCB = (PADAPTERCB)MiniportAdapterContext;
+
+ NdisWanDbgOut(DBG_TRACE, DBG_MINIPORT, ("NdisWanSetInformation: Enter Oid: 0x%4.4x", Oid));
+
+ NdisWanInterlockedInc(&AdapterCB->ulReferenceCount);
+
+ Status = NdisWanOidProc(AdapterCB,
+ Oid,
+ SET_OID,
+ InformationBuffer,
+ InformationBufferLength,
+ BytesWritten,
+ BytesNeeded);
+
+ NdisWanDbgOut(DBG_TRACE, DBG_MINIPORT, ("NdisWanSetInformation: Exit"));
+
+ NdisWanInterlockedDec(&AdapterCB->ulReferenceCount);
+
+ return (Status);
+}
+
+#ifdef USE_NDIS_MINIPORT_CALLBACK
+VOID
+DeferredCallback(
+ PADAPTERCB AdapterCB,
+ PVOID Context
+ )
+{
+ BOOLEAN Again;
+ ULONG Type = (ULONG)Context;
+
+ NdisAcquireSpinLock(&AdapterCB->Lock);
+
+ NdisWanInterlockedInc(&AdapterCB->ulReferenceCount);
+
+ do {
+ Again = FALSE;
+
+ //
+ // Chec the receive indication queue first
+ //
+ if (!IsDeferredQueueEmpty(&AdapterCB->DeferredQueue[ReceiveIndication])) {
+ NdisWanProcessReceiveIndications(AdapterCB);
+ Again = TRUE;
+ }
+
+ //
+ // Check the send complete queue
+ //
+ if (!IsDeferredQueueEmpty(&AdapterCB->DeferredQueue[SendComplete])) {
+ NdisWanProcessSendCompletes(AdapterCB);
+ Again = TRUE;
+ }
+
+ //
+ // Check the loopback queue
+ //
+ if (!IsDeferredQueueEmpty(&AdapterCB->DeferredQueue[Loopback])) {
+ NdisWanProcessLoopbacks(AdapterCB);
+ Again = TRUE;
+ }
+
+ //
+ // Check the indications queue
+ //
+ if (!IsDeferredQueueEmpty(&AdapterCB->DeferredQueue[StatusIndication])) {
+ NdisWanProcessStatusIndications(AdapterCB);
+ Again = TRUE;
+ }
+
+ } while (Again);
+
+ if (AdapterCB->Flags & RECEIVE_COMPLETE) {
+ NdisWanDoReceiveComplete(AdapterCB);
+ AdapterCB->Flags &= ~RECEIVE_COMPLETE;
+ }
+
+ AdapterCB->Flags &= ~DEFERRED_CALLBACK_SET;
+
+ NdisReleaseSpinLock(&AdapterCB->Lock);
+
+ NdisWanInterlockedDec(&AdapterCB->ulReferenceCount);
+}
+#else // end of USE_NDIS_MINIPORT_CALLBACK
+VOID
+DeferredTimerFunction(
+ PVOID System1,
+ PADAPTERCB AdapterCB,
+ PVOID System2,
+ PVOID System3
+ )
+{
+ BOOLEAN Again;
+
+ NdisAcquireSpinLock(&AdapterCB->Lock);
+
+ NdisWanInterlockedInc(&AdapterCB->ulReferenceCount);
+
+ do {
+ Again = FALSE;
+
+ //
+ // Chec the receive indication queue first
+ //
+ if (!IsDeferredQueueEmpty(&AdapterCB->DeferredQueue[ReceiveIndication])) {
+ NdisWanProcessReceiveIndications(AdapterCB);
+ Again = TRUE;
+ }
+
+ //
+ // Check the send complete queue
+ //
+ if (!IsDeferredQueueEmpty(&AdapterCB->DeferredQueue[SendComplete])) {
+ NdisWanProcessSendCompletes(AdapterCB);
+ Again = TRUE;
+ }
+
+ //
+ // Check the loopback queue
+ //
+ if (!IsDeferredQueueEmpty(&AdapterCB->DeferredQueue[Loopback])) {
+ NdisWanProcessLoopbacks(AdapterCB);
+ Again = TRUE;
+ }
+
+ //
+ // Check the indications queue
+ //
+ if (!IsDeferredQueueEmpty(&AdapterCB->DeferredQueue[StatusIndication])) {
+ NdisWanProcessStatusIndications(AdapterCB);
+ Again = TRUE;
+ }
+
+ } while (Again);
+
+ if (AdapterCB->Flags & RECEIVE_COMPLETE) {
+ NdisWanDoReceiveComplete(AdapterCB);
+ AdapterCB->Flags &= ~RECEIVE_COMPLETE;
+ }
+
+ AdapterCB->Flags &= ~DEFERRED_TIMER_SET;
+
+ NdisReleaseSpinLock(&AdapterCB->Lock);
+
+ NdisWanInterlockedDec(&AdapterCB->ulReferenceCount);
+}
+#endif // end of !USE_NDIS_MINIPORT_CALLBACK
diff --git a/private/ntos/ndis/ndiswan/ndiswan.c b/private/ntos/ndis/ndiswan/ndiswan.c
new file mode 100644
index 000000000..da5771b79
--- /dev/null
+++ b/private/ntos/ndis/ndiswan/ndiswan.c
@@ -0,0 +1,1346 @@
+/*++
+
+Copyright (c) 1990-1995 Microsoft Corporation
+
+Module Name:
+
+ Ndiswan.c
+
+Abstract:
+
+ This is the initialization file for the NdisWan driver. This driver
+ is a shim between the protocols, where it conforms to the NDIS 3.1
+ Miniport interface spec, and the WAN Miniport drivers, where it exports
+ the WAN Extensions for Miniports (it looks like a protocol to the WAN
+ Miniport drivers).
+
+Author:
+
+ Tony Bell (TonyBe) June 06, 1995
+
+Environment:
+
+ Kernel Mode
+
+Revision History:
+
+ TonyBe 06/06/95 Created
+
+--*/
+
+
+//
+// We want to initialize all of the global variables now!
+//
+#include "wan.h"
+
+EXPORT
+VOID
+NdisTapiRegisterProvider(
+ IN NDIS_HANDLE DriverHandle,
+ IN PVOID RequestProc
+ );
+
+//
+// Globals
+//
+NDISWANCB NdisWanCB; // Global control block for NdisWan
+
+WAN_GLOBAL_LIST ThresholdEventQueue; // Global thresholdevent queue
+
+WAN_GLOBAL_LIST RecvPacketQueue; // Global receive packet queue
+
+WAN_GLOBAL_LIST FreeBundleCBList; // List of free BundleCB's
+
+WAN_GLOBAL_LIST AdapterCBList; // List of NdisWan AdapterCB's
+
+WAN_GLOBAL_LIST WanAdapterCBList; // List of WAN Miniport structures
+
+WAN_GLOBAL_LIST GlobalRecvDescPool; // Global pool of free recvdesc's
+
+PCONNECTION_TABLE ConnectionTable = NULL; // Pointer to connection table
+
+PPPP_PROTOCOL_TABLE PPP_ProtocolTable = NULL; // Pointer to the PPP/Protocol lookup table
+
+NDIS_PHYSICAL_ADDRESS HighestAcceptableAddress = NDIS_PHYSICAL_ADDRESS_CONST(-1, -1);
+
+#ifdef NT
+
+NTSTATUS
+DriverEntry(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PUNICODE_STRING RegistryPath
+ )
+/*++
+Routine Name:
+
+ DriverEntry
+
+Routine Description:
+
+ This is the NT OS specific driver entry point. It kicks off initialization
+ for the driver. We return from this routine only after NdisWan has installed
+ itself as: a Miniport driver, a "transport" to the WAN Miniport drivers, and
+ has been bound to the WAN Miniport drivers.
+
+Arguments:
+
+ DriverObject - NT OS specific Object
+ RegistryPath - NT OS specific pointer to registry location for NdisWan
+
+Return Values:
+
+ STATUS_SUCCESS
+ STATUS_FAILURE
+
+--*/
+{
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+ NDIS_STRING SymbolicName = NDIS_STRING_CONST("\\DosDevices\\NdisWan");
+ NDIS_STRING Name = NDIS_STRING_CONST("\\Device\\NdisWan");
+ ULONG i;
+
+ NdisZeroMemory(&NdisWanCB, sizeof(NdisWanCB));
+
+ NdisWanCB.ulTraceLevel = DBG_CRITICAL_ERROR;
+ NdisWanCB.ulTraceMask = DBG_ALL;
+
+ NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("DriverEntry: Enter"));
+
+ //
+ // Initialize as a Miniport MAC driver first
+ //
+ NdisMInitializeWrapper(&(NdisWanCB.hNdisWrapperHandle),
+ DriverObject,
+ RegistryPath,
+ NULL);
+
+ //
+ // Initialize globals
+ //
+ NdisAllocateSpinLock(&NdisWanCB.Lock);
+
+ NdisWanCB.pDriverObject = DriverObject;
+
+ NdisZeroMemory(&AdapterCBList, sizeof(WAN_GLOBAL_LIST));
+ InitializeListHead(&(AdapterCBList.List));
+ NdisAllocateSpinLock(&AdapterCBList.Lock);
+
+ NdisZeroMemory(&WanAdapterCBList, sizeof(WAN_GLOBAL_LIST));
+ InitializeListHead(&(WanAdapterCBList.List));
+ NdisAllocateSpinLock(&WanAdapterCBList.Lock);
+
+ NdisZeroMemory(&ThresholdEventQueue, sizeof(WAN_GLOBAL_LIST));
+ InitializeListHead(&(ThresholdEventQueue.List));
+ NdisAllocateSpinLock(&ThresholdEventQueue.Lock);
+
+ NdisZeroMemory(&RecvPacketQueue, sizeof(WAN_GLOBAL_LIST));
+ InitializeListHead(&(RecvPacketQueue.List));
+ NdisAllocateSpinLock(&RecvPacketQueue.Lock);
+
+ NdisZeroMemory(&FreeBundleCBList, sizeof(WAN_GLOBAL_LIST));
+ InitializeListHead(&(FreeBundleCBList.List));
+ NdisAllocateSpinLock(&FreeBundleCBList.Lock);
+
+ NdisZeroMemory(&GlobalRecvDescPool, sizeof(WAN_GLOBAL_LIST));
+ InitializeListHead(&GlobalRecvDescPool.List);
+ NdisAllocateSpinLock(&GlobalRecvDescPool.Lock);
+
+ Status = NdisWanCreatePPPProtocolTable();
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+
+ NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_INIT,
+ ("NdisWanInitProtocolLookupTable Failed! Status: 0x%x - %s",
+ Status, NdisWanGetNdisStatus(Status)));
+
+ goto DriverEntryError;
+ }
+
+ //
+ // Initialize as a Miniport driver to the transports
+ //
+ Status = DoMiniportInit();
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+
+ NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_INIT,
+ ("DoMiniportInit Failed! Status: 0x%x - %s",
+ Status, NdisWanGetNdisStatus(Status)));
+
+ goto DriverEntryError;
+ }
+
+ //
+ // Now initialzie as a "Protocol" to the WAN Miniport drivers
+ //
+ Status = DoProtocolInit(RegistryPath);
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+
+ NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_INIT,
+ ("DoProtocolInit Failed! Status: 0x%x - %s",
+ Status, NdisWanGetNdisStatus(Status)));
+
+ goto DriverEntryError;
+ }
+
+ NdisWanReadRegistry(RegistryPath);
+
+ //
+ // Bind NdisWan to the WAN Miniport drivers
+ //
+ Status = DoWanMiniportInit();
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+
+ NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_INIT,
+ ("DoWanMiniportInit Failed! Status: 0x%x - %s",
+ Status, NdisWanGetNdisStatus(Status)));
+
+ goto DriverEntryError;
+
+ }
+
+//
+// Code commented out for PNP. We may go through DriverEntry and not have
+// any miniports bound to us yet. We will get called to bind to a WanMiniport
+// at a later time by the ProtocolBindHandler call (?).
+//
+/*
+ NdisAcquireSpinLock(&WanAdapterCBList.Lock);
+
+ if (WanAdapterCBList.ulCount == 0) {
+ NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_INIT, ("No WanAdapters installed!"));
+
+ NdisReleaseSpinLock(&WanAdapterCBList.Lock);
+
+ goto DriverEntryError;
+ }
+
+ NdisReleaseSpinLock(&WanAdapterCBList.Lock);
+*/
+
+ //
+ // Allocate and initialize the ConnectionTable
+ //
+ Status = NdisWanCreateConnectionTable(NdisWanCB.ulNumberOfLinks + 10);
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+
+ NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_INIT,
+ ("NdisWanInitConnectionTable Failed! Status: 0x%x - %s",
+ Status, NdisWanGetNdisStatus(Status)));
+
+ goto DriverEntryError;
+
+ }
+
+ //
+ // Initialize the Ioctl interface
+ //
+ for (i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) {
+
+ NdisWanCB.MajorFunction[i] = (PVOID)DriverObject->MajorFunction[i];
+ DriverObject->MajorFunction[i] = NdisWanIrpStub;
+ }
+
+ DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = NdisWanIoctl;
+
+ IoCreateDevice(DriverObject,
+ sizeof(LIST_ENTRY),
+ &Name,
+ FILE_DEVICE_NDISWAN,
+ 0,
+ FALSE,
+ (PDEVICE_OBJECT*)&NdisWanCB.pDeviceObject);
+
+ NdisWanDbgOut(DBG_INFO, DBG_INIT,
+ ("IoCreateSymbolicLink: %ls -> %ls",
+ SymbolicName.Buffer, Name.Buffer));
+
+ ((PDEVICE_OBJECT)NdisWanCB.pDeviceObject)->Flags |= DO_BUFFERED_IO;
+
+ IoCreateSymbolicLink(&SymbolicName,
+ &Name);
+
+ NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("DriverEntry: Exit"));
+
+ return (STATUS_SUCCESS);
+
+ //
+ // An error occured so we need to cleanup things
+ //
+DriverEntryError:
+ NdisWanGlobalCleanup();
+
+// NdisTerminateWrapper(NdisWanCB.hNdisWrapperHandle,
+// NdisWanCB.pDriverObject);
+
+ NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("DriverEntry: Exit Error!"));
+
+ return (STATUS_UNSUCCESSFUL);
+
+}
+
+
+VOID
+NdisWanReadRegistry(
+ IN PUNICODE_STRING RegistryPath
+ )
+/*++
+
+Routine Name:
+
+ NdisWanReadRegistry
+
+Routine Description:
+
+ This routine will read the registry values for NdisWan. These values only
+ need to be read once for all adapters as their information is global.
+
+Arguments:
+
+ WrapperConfigurationContext - Handle to registry key where NdisWan information
+ is stored.
+
+Return Values:
+
+ None
+
+--*/
+{
+ NDIS_STATUS Status;
+ PWSTR ParameterKey = L"NdisWan\\Parameters";
+ PWSTR BindKeyWord = L"Bind";
+ PWSTR ProtocolKeyWord = L"ProtocolType";
+ PWSTR PPPKeyWord = L"PPPProtocolType";
+ PWSTR FragmentSizeKeyWord = L"MinimumFragmentSize";
+ PWSTR DebugLevelKeyWord = L"DebugLevel";
+ PWSTR DebugIDKeyWord = L"DebugIdentifier";
+ RTL_QUERY_REGISTRY_TABLE QueryTable[2];
+ ULONG GenericULong;
+
+ NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("NdisWanReadRegistry: Enter"));
+
+ //
+ // Read the Bind Parameter MULTI_SZ
+ //
+ NdisZeroMemory(&QueryTable, sizeof(QueryTable));
+ QueryTable[0].QueryRoutine = BindQueryRoutine;
+ QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED;
+ QueryTable[0].Name = BindKeyWord;
+ QueryTable[0].EntryContext = NULL;
+ QueryTable[0].DefaultType = 0;
+ Status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES,
+ ParameterKey,
+ &QueryTable[0],
+ NULL,
+ NULL);
+
+
+ NdisWanDbgOut(DBG_INFO, DBG_INIT,
+ ("RtlQueryRegistry - 'Bind' Status: 0x%x",
+ Status));
+
+ //
+ // Read the ProtocolType parameter MULTI_SZ
+ //
+ NdisZeroMemory(&QueryTable, sizeof(QueryTable));
+ QueryTable[0].QueryRoutine = ProtocolTypeQueryRoutine;
+ QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED;
+ QueryTable[0].Name = ProtocolKeyWord;
+ QueryTable[0].EntryContext = (PVOID)PROTOCOL_TYPE;
+ QueryTable[0].DefaultType = 0;
+ Status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES,
+ ParameterKey,
+ &QueryTable[0],
+ NULL,
+ NULL);
+
+ NdisWanDbgOut(DBG_INFO, DBG_INIT,
+ ("RtlQueryRegistry - 'ProtocolType' Status: 0x%x",
+ Status));
+ //
+ // Read the PPPProtocolType parameter MULTI_SZ
+ //
+ NdisZeroMemory(&QueryTable, sizeof(QueryTable));
+ QueryTable[0].QueryRoutine = ProtocolTypeQueryRoutine;
+ QueryTable[0].Flags = RTL_QUERY_REGISTRY_REQUIRED;
+ QueryTable[0].Name = PPPKeyWord;
+ QueryTable[0].EntryContext = (PVOID)PPP_TYPE;
+ QueryTable[0].DefaultType = 0;
+ Status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES,
+ ParameterKey,
+ &QueryTable[0],
+ NULL,
+ NULL);
+
+ NdisWanDbgOut(DBG_INFO, DBG_INIT,
+ ("RtlQueryRegistry - 'PPPProtocolType' Status: 0x%x",
+ Status));
+
+ //
+ // Read the MinFragmentSize parameter DWORD
+ //
+ NdisWanCB.ulMinFragmentSize = 100;
+ NdisZeroMemory(&QueryTable, sizeof(QueryTable));
+ QueryTable[0].QueryRoutine = NULL;
+ QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
+ QueryTable[0].Name = FragmentSizeKeyWord;
+ QueryTable[0].EntryContext = (PVOID)&GenericULong;
+ QueryTable[0].DefaultType = 0;
+ Status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES,
+ ParameterKey,
+ &QueryTable[0],
+ NULL,
+ NULL);
+
+ NdisWanDbgOut(DBG_INFO, DBG_INIT,
+ ("RtlQueryRegistry - 'MinimumFragmentSize' Status: 0x%x",
+ Status));
+
+ if (Status == NDIS_STATUS_SUCCESS) {
+ NdisWanCB.ulMinFragmentSize = GenericULong;
+ }
+
+
+ //
+ // Read the DebugLevel parameter DWORD
+ //
+ NdisZeroMemory(&QueryTable, sizeof(QueryTable));
+ QueryTable[0].QueryRoutine = NULL;
+ QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
+ QueryTable[0].Name = DebugLevelKeyWord;
+ QueryTable[0].EntryContext = (PVOID)&GenericULong;
+ QueryTable[0].DefaultType = 0;
+ Status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES,
+ ParameterKey,
+ &QueryTable[0],
+ NULL,
+ NULL);
+
+ NdisWanDbgOut(DBG_INFO, DBG_INIT,
+ ("RtlQueryRegistry - 'DebugLevel' Status: 0x%x",
+ Status));
+
+ if (Status == NDIS_STATUS_SUCCESS) {
+ NdisWanCB.ulTraceLevel = GenericULong;
+ }
+
+ //
+ // Read the DebugIdentifier parameter DWORD
+ //
+ NdisZeroMemory(&QueryTable, sizeof(QueryTable));
+ QueryTable[0].QueryRoutine = NULL;
+ QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
+ QueryTable[0].Name = DebugIDKeyWord;
+ QueryTable[0].EntryContext = (PVOID)&GenericULong;
+ QueryTable[0].DefaultType = 0;
+ Status = RtlQueryRegistryValues(RTL_REGISTRY_SERVICES,
+ ParameterKey,
+ &QueryTable[0],
+ NULL,
+ NULL);
+
+ NdisWanDbgOut(DBG_INFO, DBG_INIT,
+ ("RtlQueryRegistry - 'DebugID' Status: 0x%x",
+ Status));
+
+ if (Status == NDIS_STATUS_SUCCESS) {
+ NdisWanCB.ulTraceMask = GenericULong;
+ }
+
+ NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("NdisWanReadRegistry: Exit"));
+}
+
+NTSTATUS
+BindQueryRoutine(
+ IN PWSTR ValueName,
+ IN ULONG ValueType,
+ IN PVOID ValueData,
+ IN ULONG ValueLength,
+ IN PVOID Context,
+ IN PVOID EntryContext
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("BindQueryRoutine: Enter"));
+ NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("MiniportName %ls", ValueData));
+
+ //
+ // Create the WanAdapterCB
+ //
+ Status = NdisWanCreateWanAdapterCB(ValueData);
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+ NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_INIT,
+ ("NdisWanCreateWanAdapterCB Failed! Status: 0x%x - %s",
+ Status, NdisWanGetNdisStatus(Status)));
+
+ }
+
+ NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("BindQueryRoutine: Exit Status: 0x%x", Status));
+
+ return (Status);
+}
+
+NTSTATUS
+ProtocolTypeQueryRoutine(
+ IN PWSTR ValueName,
+ IN ULONG ValueType,
+ IN PVOID ValueData,
+ IN ULONG ValueLength,
+ IN PVOID Context,
+ IN PVOID EntryContext
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ NDIS_STRING String;
+ ULONG Value;
+ NTSTATUS Status = STATUS_SUCCESS;
+
+ NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("ProtocolTypeQueryRoutine: Enter"));
+
+ //
+ // Convert to an NDIS_STRING
+ //
+ NdisWanStringToNdisString(&String, ValueData);
+
+ //
+ // Convert to an integer
+ //
+ NdisWanNdisStringToInteger(&String, &Value);
+
+ NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("ProtocolID 0x%x", Value));
+
+ NdisWanFreeNdisString(&String);
+
+ //
+ // Place in table
+ //
+ InsertPPP_ProtocolID(Value, (ULONG)EntryContext);
+
+ NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("ProtocolTypeQueryRoutine: Exit"));
+
+ return (Status);
+}
+
+
+#endif // NT specific code
+
+
+
+NDIS_STATUS
+DoMiniportInit(
+ VOID
+ )
+/*++
+
+Routine Name:
+
+ DoMiniportInit
+
+Routine Description:
+
+ This routines registers NdisWan as a Miniport driver with the NDIS wrapper.
+ The wrapper will now call NdisWanInitialize once for each adapter instance
+ of NdisWan that is in the registry.
+
+Arguments:
+
+ None
+
+Return Values:
+
+ NDIS_STATUS_SUCCESS
+ NDIS_STATUS_BAD_VERSION
+ NDIS_STATUS_FAILURE
+
+--*/
+{
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+ NDIS_MINIPORT_CHARACTERISTICS MiniportChars;
+
+ NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("DoMiniportInit: Enter"));
+
+ NdisZeroMemory(&MiniportChars, sizeof(MiniportChars));
+
+ MiniportChars.MajorNdisVersion = 3;
+ MiniportChars.MinorNdisVersion = 0;
+ MiniportChars.HaltHandler = NdisWanHalt;
+ MiniportChars.InitializeHandler = NdisWanInitialize;
+ MiniportChars.QueryInformationHandler = NdisWanQueryInformation;
+ MiniportChars.ReconfigureHandler = NdisWanReconfigure;
+ MiniportChars.ResetHandler = NdisWanReset;
+ MiniportChars.SendHandler = NdisWanSend;
+ MiniportChars.SetInformationHandler = NdisWanSetInformation;
+ MiniportChars.TransferDataHandler = NdisWanTransferData;
+
+ //
+ // Since we don't have any hardware to worry about we will
+ // not handle any of the interrupt stuff!
+ //
+ MiniportChars.DisableInterruptHandler = NULL;
+ MiniportChars.EnableInterruptHandler = NULL;
+ MiniportChars.HandleInterruptHandler = NULL;
+ MiniportChars.ISRHandler = NULL;
+
+ //
+ // We will disable the check for hang timeout so we do not
+ // need a check for hang handler!
+ //
+// MiniportChars.CheckForHangHandler = NdisWanCheckForHang;
+ MiniportChars.CheckForHangHandler = NULL;
+
+ Status = NdisMRegisterMiniport(NdisWanCB.hNdisWrapperHandle,
+ &MiniportChars,
+ sizeof(MiniportChars));
+
+ NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("DoMiniportInit: Exit"));
+
+ return (Status);
+}
+
+
+
+NDIS_STATUS
+DoProtocolInit(
+ IN PUNICODE_STRING RegistryPath
+ )
+/*++
+
+Routine Name:
+
+ DoProtocolInit
+
+Routine Description:
+
+ This function registers NdisWan as a protocol with the NDIS wrapper.
+
+Arguments:
+
+ None
+
+Return Values:
+
+ NDIS_STATUS_BAD_CHARACTERISTICS
+ NDIS_STATUS_BAD_VERSION
+ NDIS_STATUS_RESOURCES
+ NDIS_STATUS_SUCCESS
+
+--*/
+{
+//
+// The name of the "transport" side of NdisWan
+//
+ NDIS_PROTOCOL_CHARACTERISTICS ProtocolChars;
+ NDIS_STATUS Status;
+ NDIS_STRING NdisWanName = NDIS_STRING_CONST("\\Device\\NdisWan");
+
+
+ NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("DoProtocolInit: Enter"));
+
+ NdisZeroMemory(&ProtocolChars, sizeof(ProtocolChars));
+
+
+ ProtocolChars.Name.Length = NdisWanName.Length;
+ ProtocolChars.Name.Buffer = (PVOID)NdisWanName.Buffer;
+
+ ProtocolChars.MajorNdisVersion = 3;
+ ProtocolChars.MinorNdisVersion = 0;
+ ProtocolChars.CloseAdapterCompleteHandler = NdisWanCloseAdapterComplete;
+ ProtocolChars.StatusHandler = NdisWanIndicateStatus;
+ ProtocolChars.StatusCompleteHandler = NdisWanIndicateStatusComplete;
+ ProtocolChars.OpenAdapterCompleteHandler = NdisWanOpenAdapterComplete;
+ ProtocolChars.RequestCompleteHandler = NdisWanRequestComplete;
+ ProtocolChars.ResetCompleteHandler = NdisWanResetComplete;
+ ProtocolChars.WanSendCompleteHandler = NdisWanSendCompleteHandler;
+ ProtocolChars.TransferDataCompleteHandler = NdisWanTransferDataComplete;
+ ProtocolChars.WanReceiveHandler = NdisWanReceiveIndication;
+ ProtocolChars.ReceiveCompleteHandler = NdisWanReceiveComplete;
+
+ NdisRegisterProtocol(&Status,
+ &NdisWanCB.hProtocolHandle,
+ (PNDIS_PROTOCOL_CHARACTERISTICS)&ProtocolChars,
+ sizeof(NDIS_PROTOCOL_CHARACTERISTICS) + ProtocolChars.Name.Length);
+
+ NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("DoProtocolInit: Exit"));
+
+ return (Status);
+}
+
+NDIS_STATUS
+DoWanMiniportInit(
+ VOID
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ PWAN_ADAPTERCB pWanAdapterCB;
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+ NDIS_MEDIUM WanMediumSubType;
+ NDIS_WAN_INFO WanInfo;
+ NDIS_REQUEST NdisRequest;
+
+ //
+ // For each WAN Miniport that we have a WANAdapterCB for we will
+ // open the WAN Miniport thus binding to it. We will also query
+ // each WAN Miniport adapter to get information about it.
+ //
+ NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("DoWanMiniportInit: Enter"));
+
+ NdisAcquireSpinLock(&WanAdapterCBList.Lock);
+
+ for (pWanAdapterCB = (PWAN_ADAPTERCB)WanAdapterCBList.List.Flink;
+ (PVOID)pWanAdapterCB != (PVOID)&(WanAdapterCBList.List);
+ pWanAdapterCB = (PWAN_ADAPTERCB)pWanAdapterCB->Linkage.Flink) {
+
+ NdisReleaseSpinLock(&WanAdapterCBList.Lock);
+
+ Status = NdisWanOpenWanAdapter(pWanAdapterCB);
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+ PWAN_ADAPTERCB pPrevWanAdapterCB = (PWAN_ADAPTERCB)pWanAdapterCB->Linkage.Blink;
+
+ RemoveEntryList(&pWanAdapterCB->Linkage);
+ WanAdapterCBList.ulCount--;
+
+ NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_INIT, ("Failed to bind to %ls! Error 0x%x - %s",
+ pWanAdapterCB->MiniportName.Buffer, Status, NdisWanGetNdisStatus(Status)));
+
+ NdisWanDestroyWanAdapterCB(pWanAdapterCB);
+
+ pWanAdapterCB = pPrevWanAdapterCB;
+
+ NdisAcquireSpinLock(&WanAdapterCBList.Lock);
+ continue;
+ }
+
+ NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("Successful Binding to %ls!",
+ pWanAdapterCB->MiniportName.Buffer));
+
+ //
+ // Get the medium subtype. We don't use this info right now but
+ // maybe someday...
+ //
+ NdisRequest.RequestType = NdisRequestQueryInformation;
+ NdisRequest.DATA.QUERY_INFORMATION.Oid = OID_WAN_MEDIUM_SUBTYPE;
+ NdisRequest.DATA.QUERY_INFORMATION.InformationBuffer = &WanMediumSubType;
+ NdisRequest.DATA.QUERY_INFORMATION.InformationBufferLength = sizeof(WanMediumSubType);
+
+ Status = NdisWanSubmitNdisRequest(pWanAdapterCB,
+ &NdisRequest,
+ SYNC,
+ NDISWAN);
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+ NdisWanDbgOut(DBG_FAILURE, DBG_INIT, ("Error returned from OID_WAN_MEDIUM_SUBTYPE! Error 0x%x - %s",
+ Status, NdisWanGetNdisStatus(Status)));
+
+ NdisAcquireSpinLock(&WanAdapterCBList.Lock);
+ continue;
+ }
+
+ pWanAdapterCB->MediumSubType = WanMediumSubType;
+
+ //
+ // Get more information about the WAN Miniport that we are bound to!
+ //
+ NdisZeroMemory(&WanInfo, sizeof(WanInfo));
+ NdisRequest.RequestType = NdisRequestQueryInformation;
+ NdisRequest.DATA.QUERY_INFORMATION.Oid = OID_WAN_GET_INFO;
+ NdisRequest.DATA.QUERY_INFORMATION.InformationBuffer = &WanInfo;
+ NdisRequest.DATA.QUERY_INFORMATION.InformationBufferLength = sizeof(WanInfo);
+
+ Status = NdisWanSubmitNdisRequest(pWanAdapterCB,
+ &NdisRequest,
+ SYNC,
+ NDISWAN);
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+ NdisWanDbgOut(DBG_FAILURE, DBG_INIT, ("Error returned from OID_WAN_GET_INFO! Error 0x%x - %s",
+ Status, NdisWanGetNdisStatus(Status)));
+
+ NdisAcquireSpinLock(&WanAdapterCBList.Lock);
+ continue;
+ }
+
+ NdisMoveMemory(&pWanAdapterCB->WanInfo, &WanInfo, sizeof(NDIS_WAN_INFO));
+
+ NdisWanCB.ulNumberOfLinks += pWanAdapterCB->WanInfo.Endpoints;
+
+ NdisAcquireSpinLock(&FreeBundleCBList.Lock);
+ FreeBundleCBList.ulMaxCount = NdisWanCB.ulNumberOfLinks;
+ NdisReleaseSpinLock(&FreeBundleCBList.Lock);
+
+ if (pWanAdapterCB->WanInfo.FramingBits & TAPI_PROVIDER) {
+
+ //
+ // Tell tapi about this device
+ //
+ NdisTapiRegisterProvider(pWanAdapterCB, NdisWanTapiRequestProc);
+
+ }
+
+ NdisAcquireSpinLock(&WanAdapterCBList.Lock);
+ }
+
+//
+// The following lines are commented out to take into account pnp.
+// We may not have any miniports to bind to initially but get called
+// to bind to them later!
+//
+// if (WanAdapterCBList.ulCount == 0)
+// Status = NDIS_STATUS_ADAPTER_NOT_FOUND;
+// else
+ Status = NDIS_STATUS_SUCCESS;
+
+ NdisReleaseSpinLock(&WanAdapterCBList.Lock);
+
+ NdisWanDbgOut(DBG_TRACE, DBG_INIT, ("DoWanMiniportInit: Exit"));
+
+ return (Status);
+}
+
+VOID
+InsertPPP_ProtocolID(
+ IN ULONG Value,
+ IN ULONG ValueType
+ )
+/*++
+
+Routine Name:
+
+ InsertPPP_ProtocolID
+
+Routine Description:
+
+ This routine takes a protocol value or a PPP protocol value and inserts it
+ into the appropriate lookup table.
+
+Arguments:
+
+ Value - Either a ProtocolID or PPP ProtocolID
+
+ ValueType - Either PROTOCOL_TYPE or PPP_TYPE
+
+Return Values:
+
+--*/
+{
+ ULONG i;
+ ULONG ArraySize = PPP_ProtocolTable->ulArraySize;
+ PUSHORT ValueArray;
+
+ //
+ // Figure out which array we should be looking at for
+ // this value type
+ //
+ if (ValueType == PROTOCOL_TYPE) {
+ ValueArray = PPP_ProtocolTable->ProtocolID;
+ } else {
+ ValueArray = PPP_ProtocolTable->PPPProtocolID;
+ }
+
+ NdisAcquireSpinLock(&PPP_ProtocolTable->Lock);
+
+ //
+ // First check to see if this value is already in the array
+ //
+ for (i = 0; i < ArraySize; i++) {
+
+ if (ValueArray[i] == (USHORT)Value) {
+
+ //
+ // If it is then we just update the value
+ //
+ ValueArray[i] = (USHORT)Value;
+ break;
+
+ }
+ }
+
+ //
+ // We did not find the value in the array so
+ // we will add it at the 1st available spot
+ //
+ if (i >= ArraySize) {
+
+ for (i = 0; i < ArraySize; i++) {
+
+ //
+ // We are looking for an empty slot to add
+ // the new value to
+ //
+ if (ValueArray[i] == 0) {
+
+ ValueArray[i] = (USHORT)Value;
+
+ if (ValueType == PROTOCOL_TYPE) {
+ NdisWanCB.ulNumberOfProtocols++;
+ }
+
+ break;
+ }
+ }
+ }
+
+ NdisReleaseSpinLock(&PPP_ProtocolTable->Lock);
+}
+
+USHORT
+GetPPP_ProtocolID(
+ IN USHORT Value,
+ IN ULONG ValueType
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ ULONG i;
+ ULONG ArraySize = PPP_ProtocolTable->ulArraySize;
+ PUSHORT ValueArray, ReturnValueArray;
+ USHORT ReturnValue = INVALID_PROTOCOL;
+
+ //
+ // Figure out which array we should be looking at for
+ // this value type
+ //
+ if (ValueType == PROTOCOL_TYPE) {
+ ValueArray = PPP_ProtocolTable->ProtocolID;
+ ReturnValueArray = PPP_ProtocolTable->PPPProtocolID;
+ } else {
+ ValueArray = PPP_ProtocolTable->PPPProtocolID;
+ ReturnValueArray = PPP_ProtocolTable->ProtocolID;
+ }
+
+ NdisAcquireSpinLock(&PPP_ProtocolTable->Lock);
+
+ for (i = 0; i < ArraySize; i++) {
+ if (ValueArray[i] == Value) {
+ ReturnValue = ReturnValueArray[i];
+ break;
+ }
+ }
+
+ NdisReleaseSpinLock(&PPP_ProtocolTable->Lock);
+
+ return (ReturnValue);
+}
+
+NDIS_HANDLE
+InsertLinkInConnectionTable(
+ IN PLINKCB LinkCB
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ ULONG Index;
+ PLINKCB *LinkArray = ConnectionTable->LinkArray;
+
+ NdisAcquireSpinLock(&ConnectionTable->Lock);
+
+ //
+ // We are doing a linear search for an empty spot in
+ // the link array
+ //
+ for (Index = 1; Index < ConnectionTable->ulArraySize; Index++) {
+ if (LinkArray[Index] == NULL) {
+ LinkArray[Index] = LinkCB;
+ ConnectionTable->ulNumActiveLinks++;
+ LinkCB->hLinkHandle = (NDIS_HANDLE)Index;
+ break;
+ }
+ }
+
+ ASSERT(Index < ConnectionTable->ulArraySize);
+
+ NdisReleaseSpinLock(&ConnectionTable->Lock);
+
+ return ((NDIS_HANDLE)Index);
+}
+
+VOID
+RemoveLinkFromConnectionTable(
+ IN PLINKCB LinkCB
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ ULONG Index = (ULONG)LinkCB->hLinkHandle;
+ PLINKCB *LinkArray = ConnectionTable->LinkArray;
+
+ NdisAcquireSpinLock(&ConnectionTable->Lock);
+
+ if (LinkArray[Index] != NULL) {
+
+ ASSERT(LinkCB == LinkArray[Index]);
+
+ LinkArray[Index] = NULL;
+
+ ConnectionTable->ulNumActiveLinks--;
+ } else {
+ NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_INIT, ("LinkCB not in connection table! LinkCB: 0x%8.8x", LinkCB));
+ ASSERT(0);
+ }
+
+ NdisReleaseSpinLock(&ConnectionTable->Lock);
+}
+
+NDIS_HANDLE
+InsertBundleInConnectionTable(
+ IN PBUNDLECB BundleCB
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ ULONG Index;
+ PBUNDLECB *BundleArray = ConnectionTable->BundleArray;
+
+ NdisAcquireSpinLock(&ConnectionTable->Lock);
+
+ //
+ // We are doing a linear search for an empty spot in
+ // the link array
+ //
+ for (Index = 1; Index < ConnectionTable->ulArraySize; Index++) {
+ if (BundleArray[Index] == NULL) {
+ BundleArray[Index] = BundleCB;
+ ConnectionTable->ulNumActiveBundles++;
+ BundleCB->hBundleHandle = (NDIS_HANDLE)Index;
+ break;
+ }
+ }
+
+ InsertTailList(&ConnectionTable->BundleList, &BundleCB->Linkage);
+
+ ASSERT(Index != ConnectionTable->ulArraySize);
+
+ NdisReleaseSpinLock(&ConnectionTable->Lock);
+
+ return ((NDIS_HANDLE)Index);
+}
+
+VOID
+RemoveBundleFromConnectionTable(
+ IN PBUNDLECB BundleCB
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ ULONG Index = (ULONG)BundleCB->hBundleHandle;
+ PBUNDLECB *BundleArray = ConnectionTable->BundleArray;
+
+ NdisAcquireSpinLock(&ConnectionTable->Lock);
+
+ if (BundleArray[Index] != NULL) {
+
+ ASSERT(BundleCB == BundleArray[Index]);
+
+ RemoveEntryList(&BundleCB->Linkage);
+
+ BundleArray[Index] = NULL;
+
+ ConnectionTable->ulNumActiveBundles--;
+ } else {
+ NdisWanDbgOut(DBG_CRITICAL_ERROR, DBG_INIT, ("BundleCB not in connection table! BundleCB: 0x%8.8x", BundleCB));
+ ASSERT(0);
+ }
+
+ NdisReleaseSpinLock(&ConnectionTable->Lock);
+}
+
+VOID
+NdisWanGlobalCleanup(
+ VOID
+ )
+/*++
+
+Routine Name:
+
+ NdisWanGlobalCleanup
+
+Routine Description:
+ This routine is responsible for cleaning up all allocated resources.
+
+Arguments:
+
+ None
+
+Return Values:
+
+ None
+
+--*/
+{
+ //
+ // Stop all timers
+ //
+
+ //
+ // Complete all outstanding requests
+ //
+
+ //
+ // Free all of the AdapterCB's
+ //
+ NdisAcquireSpinLock(&AdapterCBList.Lock);
+ while (!IsListEmpty(&AdapterCBList.List)) {
+ PADAPTERCB AdapterCB;
+
+ AdapterCB = (PADAPTERCB)RemoveHeadList(&AdapterCBList.List);
+ NdisWanFreeMemory(AdapterCB);
+ }
+ NdisReleaseSpinLock(&AdapterCBList.Lock);
+
+ //
+ // Free all of the WanAdapterCB's
+ //
+ NdisAcquireSpinLock(&WanAdapterCBList.Lock);
+ while (!IsListEmpty(&WanAdapterCBList.List)) {
+ PWAN_ADAPTERCB WanAdapterCB;
+
+ WanAdapterCB = (PWAN_ADAPTERCB)RemoveHeadList(&WanAdapterCBList.List);
+ NdisWanFreeMemory(WanAdapterCB);
+ }
+ NdisReleaseSpinLock(&WanAdapterCBList.Lock);
+
+ //
+ // Free all of the BundleCB's
+ //
+
+ //
+ // Free all of the LinkCB's
+ //
+
+ //
+ // Free globals
+ //
+ if (ConnectionTable != NULL) {
+ NdisWanFreeMemory(ConnectionTable);
+ }
+
+ if (PPP_ProtocolTable != NULL) {
+ NdisWanFreeMemory(PPP_ProtocolTable);
+ }
+
+ //
+ // Terminate the wrapper
+ //
+ NdisTerminateWrapper(NdisWanCB.hNdisWrapperHandle,
+ NdisWanCB.pDriverObject);
+}
+
+BOOLEAN
+IsHandleValid(
+ USHORT usHandleType,
+ NDIS_HANDLE hHandle
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ BOOLEAN RetValue = FALSE;
+ PVOID Cb;
+
+ if (usHandleType == LINKHANDLE) {
+
+ LINKCB_FROM_LINKH((PLINKCB)Cb, hHandle);
+
+ } else if (usHandleType == BUNDLEHANDLE) {
+
+ BUNDLECB_FROM_BUNDLEH((PBUNDLECB)Cb, hHandle);
+
+ }
+
+ if (Cb != NULL) {
+ RetValue = TRUE;
+ }
+
+ return (RetValue);
+}
+
+
+#if DBG // Debug
+
+PUCHAR
+NdisWanGetNdisStatus(
+ NDIS_STATUS GeneralStatus
+ )
+/*++
+
+Routine Name:
+
+ NdisWanGetNdisStatus
+
+Routine Description:
+
+ This routine returns a pointer to the string describing the NDIS error
+ denoted by GeneralStatus
+
+Arguments:
+
+ GeneralStatus - The NDIS status you wish to make readable
+
+Return Values:
+
+ Returns a pointer to a string describing GeneralStatus
+
+--*/
+{
+ static NDIS_STATUS Status[] = {
+ NDIS_STATUS_SUCCESS,
+ NDIS_STATUS_PENDING,
+
+ NDIS_STATUS_ADAPTER_NOT_FOUND,
+ NDIS_STATUS_ADAPTER_NOT_OPEN,
+ NDIS_STATUS_ADAPTER_NOT_READY,
+ NDIS_STATUS_ADAPTER_REMOVED,
+ NDIS_STATUS_BAD_CHARACTERISTICS,
+ NDIS_STATUS_BAD_VERSION,
+ NDIS_STATUS_CLOSING,
+ NDIS_STATUS_DEVICE_FAILED,
+ NDIS_STATUS_FAILURE,
+ NDIS_STATUS_INVALID_DATA,
+ NDIS_STATUS_INVALID_LENGTH,
+ NDIS_STATUS_INVALID_OID,
+ NDIS_STATUS_INVALID_PACKET,
+ NDIS_STATUS_MULTICAST_FULL,
+ NDIS_STATUS_NOT_INDICATING,
+ NDIS_STATUS_NOT_RECOGNIZED,
+ NDIS_STATUS_NOT_RESETTABLE,
+ NDIS_STATUS_NOT_SUPPORTED,
+ NDIS_STATUS_OPEN_FAILED,
+ NDIS_STATUS_OPEN_LIST_FULL,
+ NDIS_STATUS_REQUEST_ABORTED,
+ NDIS_STATUS_RESET_IN_PROGRESS,
+ NDIS_STATUS_RESOURCES,
+ NDIS_STATUS_UNSUPPORTED_MEDIA
+ };
+ static PUCHAR String[] = {
+ "SUCCESS",
+ "PENDING",
+
+ "ADAPTER_NOT_FOUND",
+ "ADAPTER_NOT_OPEN",
+ "ADAPTER_NOT_READY",
+ "ADAPTER_REMOVED",
+ "BAD_CHARACTERISTICS",
+ "BAD_VERSION",
+ "CLOSING",
+ "DEVICE_FAILED",
+ "FAILURE",
+ "INVALID_DATA",
+ "INVALID_LENGTH",
+ "INVALID_OID",
+ "INVALID_PACKET",
+ "MULTICAST_FULL",
+ "NOT_INDICATING",
+ "NOT_RECOGNIZED",
+ "NOT_RESETTABLE",
+ "NOT_SUPPORTED",
+ "OPEN_FAILED",
+ "OPEN_LIST_FULL",
+ "REQUEST_ABORTED",
+ "RESET_IN_PROGRESS",
+ "RESOURCES",
+ "UNSUPPORTED_MEDIA"
+ };
+
+ static UCHAR BadStatus[] = "UNDEFINED";
+#define StatusCount (sizeof(Status)/sizeof(NDIS_STATUS))
+ INT i;
+
+ for (i=0; i<StatusCount; i++)
+ if (GeneralStatus == Status[i])
+ return String[i];
+ return BadStatus;
+#undef StatusCount
+}
+#endif // End Debug
+
+
diff --git a/private/ntos/ndis/ndiswan/ndiswan.rc b/private/ntos/ndis/ndiswan/ndiswan.rc
new file mode 100644
index 000000000..902eca593
--- /dev/null
+++ b/private/ntos/ndis/ndiswan/ndiswan.rc
@@ -0,0 +1,43 @@
+#include <windows.h>
+#include <ntverp.h>
+
+/*-----------------------------------------------*/
+/* the following lines are specific to this file */
+/*-----------------------------------------------*/
+
+/* VER_FILETYPE, VER_FILESUBTYPE, VER_FILEDESCRIPTION_STR
+ * and VER_INTERNALNAME_STR must be defined before including COMMON.VER
+ * The strings don't need a '\0', since common.ver has them.
+ */
+#define VER_FILETYPE VFT_DRV
+/* possible values: VFT_UNKNOWN
+ VFT_APP
+ VFT_DLL
+ VFT_DRV
+ VFT_FONT
+ VFT_VXD
+ VFT_STATIC_LIB
+*/
+#define VER_FILESUBTYPE VFT2_DRV_NETWORK
+/* possible values VFT2_UNKNOWN
+ VFT2_DRV_PRINTER
+ VFT2_DRV_KEYBOARD
+ VFT2_DRV_LANGUAGE
+ VFT2_DRV_DISPLAY
+ VFT2_DRV_MOUSE
+ VFT2_DRV_NETWORK
+ VFT2_DRV_SYSTEM
+ VFT2_DRV_INSTALLABLE
+ VFT2_DRV_SOUND
+ VFT2_DRV_COMM
+*/
+#define VER_FILEDESCRIPTION_STR "MS WAN Wrapper Network Driver"
+#define VER_INTERNALNAME_STR "NDISWAN.SYS"
+
+#define EXPORT_CONTROLLED
+
+#ifndef ENCRYPT_128BIT
+#define EXPORT
+#endif
+
+#include "common.ver"
diff --git a/private/ntos/ndis/ndiswan/protocol.c b/private/ntos/ndis/ndiswan/protocol.c
new file mode 100644
index 000000000..c67bad125
--- /dev/null
+++ b/private/ntos/ndis/ndiswan/protocol.c
@@ -0,0 +1,723 @@
+/*++
+
+Copyright (c) 1990-1995 Microsoft Corporation
+
+Module Name:
+
+ Protocol.c
+
+Abstract:
+
+ This file contains the procedures that makeup most of the NDIS 3.1
+ Protocol interface. This interface is what NdisWan exposes to the
+ WAN Miniports below. NdisWan is not really a protocol and does not
+ do TDI, but is a shim that sits between the protocols and the
+ WAN Miniport drivers.
+
+
+Author:
+
+ Tony Bell (TonyBe) June 06, 1995
+
+Environment:
+
+ Kernel Mode
+
+Revision History:
+
+ TonyBe 06/06/95 Created
+
+--*/
+
+#include "wan.h"
+
+EXPORT
+VOID
+NdisTapiIndicateStatus(
+ IN NDIS_HANDLE BindingContext,
+ IN PVOID StatusBuffer,
+ IN UINT StatusBufferLength
+);
+
+NDIS_STATUS
+DoLineUpWork(
+ IN PPROTOCOLCB ProtocolCB
+ );
+
+NDIS_STATUS
+DoLineDownWork(
+ PPROTOCOLCB ProtocolCB
+ );
+
+NDIS_STATUS
+NdisWanOpenWanAdapter(
+ IN PWAN_ADAPTERCB pWanAdapterCB
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ NDIS_STATUS Status, OpenErrorStatus;
+ ULONG SelectedMediumIndex;
+ NDIS_MEDIUM MediumArray[] = {NdisMediumWan};
+
+ NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("NdisWanOpenAdapter: Enter - AdapterName %ls", pWanAdapterCB->MiniportName.Buffer));
+
+ //
+ // This is the only initialization of this event
+ //
+ NdisWanInitializeNotificationEvent(&pWanAdapterCB->NotificationEvent);
+
+ NdisOpenAdapter(&Status,
+ &OpenErrorStatus,
+ &(pWanAdapterCB->hNdisBindingHandle),
+ &SelectedMediumIndex,
+ MediumArray,
+ sizeof(MediumArray) / sizeof(NDIS_MEDIUM),
+ NdisWanCB.hProtocolHandle,
+ (NDIS_HANDLE)pWanAdapterCB,
+ &(pWanAdapterCB->MiniportName),
+ 0,
+ NULL);
+
+ if (Status == NDIS_STATUS_PENDING) {
+
+ NdisWanWaitForNotificationEvent(&pWanAdapterCB->NotificationEvent);
+
+ Status = pWanAdapterCB->NotificationStatus;
+
+ NdisWanClearNotificationEvent(&pWanAdapterCB->NotificationEvent);
+ }
+
+ //
+ // Medium type must be WAN!
+ //
+ pWanAdapterCB->MediumType = NdisMediumWan;
+
+ NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("NdisWanOpenAdapter: Exit"));
+
+ return (Status);
+}
+
+VOID
+NdisWanOpenAdapterComplete(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN NDIS_STATUS Status,
+ IN NDIS_STATUS OpenErrorStatus
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ PWAN_ADAPTERCB pWanAdapterCB = (PWAN_ADAPTERCB)ProtocolBindingContext;
+
+ NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("NdisWanOpenAdapterComplete: Enter - WanAdapterCB 0x%4.4x", pWanAdapterCB));
+
+ pWanAdapterCB->NotificationStatus = Status;
+
+ NdisWanSetNotificationEvent(&pWanAdapterCB->NotificationEvent);
+
+ NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("NdisWanOpenAdapterComplete: Exit"));
+}
+
+VOID
+NdisWanCloseAdapterComplete(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN NDIS_STATUS Status
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ PWAN_ADAPTERCB pWanAdapterCB = (PWAN_ADAPTERCB)ProtocolBindingContext;
+
+ NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("NdisWanCloseAdapterComplete: Enter"));
+ NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("WanAdapterCB 0x%4.4x", pWanAdapterCB));
+
+ pWanAdapterCB->NotificationStatus = Status;
+
+ NdisWanSetNotificationEvent(&pWanAdapterCB->NotificationEvent);
+
+ NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("NdisWanCloseAdapterComplete: Exit"));
+}
+
+VOID
+NdisWanResetComplete(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN NDIS_STATUS Status
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("NdisWanResetComplete: Enter"));
+
+ NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("NdisWanResetComplete: Exit"));
+}
+
+
+
+VOID
+NdisWanTransferDataComplete(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN PNDIS_PACKET pNdisPacket,
+ IN NDIS_STATUS Status,
+ IN UINT BytesTransferred
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("NdisWanTransferDataComplete: Enter"));
+
+ NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("NdisWanTransferDataComplete: Exit"));
+}
+
+VOID
+NdisWanRequestComplete(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN PNDIS_REQUEST NdisRequest,
+ IN NDIS_STATUS Status
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ PWAN_ADAPTERCB pWanAdapterCB = (PWAN_ADAPTERCB)ProtocolBindingContext;
+ PWAN_REQUEST pWanRequest = GetWanRequest(pWanAdapterCB, NdisRequest);
+
+ NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("NdisWanRequestComplete: Enter - pWanRequest: 0x%8.8x", pWanRequest));
+
+ pWanRequest->NotificationStatus = Status;
+
+ switch (pWanRequest->Origin) {
+ case NDISTAPI:
+ NdisWanTapiRequestComplete(pWanAdapterCB, pWanRequest);
+ break;
+
+ default:
+ NdisWanSetNotificationEvent(&pWanRequest->NotificationEvent);
+ break;
+
+ }
+
+ NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("NdisWanRequestComplete: Exit"));
+}
+
+VOID
+NdisWanIndicateStatus(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN NDIS_STATUS GeneralStatus,
+ IN PVOID StatusBuffer,
+ IN UINT StatusBufferSize
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ PWAN_ADAPTERCB pWanAdapterCB = (PWAN_ADAPTERCB)ProtocolBindingContext;
+
+ NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("NdisWanIndicateStatus: Enter"));
+
+ switch (GeneralStatus) {
+ case NDIS_STATUS_WAN_LINE_UP:
+ NdisWanLineUpIndication(pWanAdapterCB,
+ StatusBuffer,
+ StatusBufferSize);
+ break;
+
+ case NDIS_STATUS_WAN_LINE_DOWN:
+ NdisWanLineDownIndication(pWanAdapterCB,
+ StatusBuffer,
+ StatusBufferSize);
+ break;
+
+ case NDIS_STATUS_WAN_FRAGMENT:
+ NdisWanFragmentIndication(pWanAdapterCB,
+ StatusBuffer,
+ StatusBufferSize);
+ break;
+
+ case NDIS_STATUS_TAPI_INDICATION:
+ NdisWanTapiIndication(pWanAdapterCB,
+ StatusBuffer,
+ StatusBufferSize);
+
+ break;
+
+ default:
+ NdisWanDbgOut(DBG_INFO, DBG_PROTOCOL, ("Unknown Status Indication: 0x%8.8x", GeneralStatus));
+ break;
+ }
+
+ NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("NdisWanIndicateStatus: Exit"));
+}
+
+VOID
+NdisWanIndicateStatusComplete(
+ IN NDIS_HANDLE BindingContext
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("NdisWanIndicateStatusComplete: Enter"));
+
+ NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("NdisWanIndicateStatusComplete: Exit"));
+}
+
+NDIS_STATUS
+DoNewLineUpToProtocol(
+ PPROTOCOLCB ProtocolCB
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ PADAPTERCB AdapterCB;
+ NDIS_STATUS Status = STATUS_SUCCESS;
+ PBUNDLECB BundleCB = ProtocolCB->BundleCB;
+
+ NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("DoNewLineupToProtocol: Enter"));
+
+ //
+ // Find the adapter that this lineup is for
+ //
+ NdisAcquireSpinLock(&AdapterCBList.Lock);
+
+ for (AdapterCB = (PADAPTERCB)AdapterCBList.List.Flink;
+ (PVOID)AdapterCB != (PVOID)&AdapterCBList.List;
+ AdapterCB = (PADAPTERCB)AdapterCB->Linkage.Flink) {
+
+ if (NdisWanCompareNdisString(&AdapterCB->AdapterName,
+ &ProtocolCB->BindingName)) {
+ break;
+
+ }
+ }
+
+ NdisReleaseSpinLock(&AdapterCBList.Lock);
+
+ if ((PVOID)AdapterCB != (PVOID)&AdapterCBList.List) {
+
+ ASSERT(AdapterCB->ProtocolType == ProtocolCB->usProtocolType);
+
+ ETH_COPY_NETWORK_ADDRESS(ProtocolCB->NdisWanAddress, AdapterCB->NetworkAddress);
+
+ //
+ // Put the protocol index in place
+ //
+ FillNdisWanProtocolIndex(ProtocolCB->NdisWanAddress, ProtocolCB->hProtocolHandle);
+
+ //
+ // Put the bundle index in place
+ //
+ FillNdisWanBundleIndex(ProtocolCB->NdisWanAddress, BundleCB->hBundleHandle);
+
+ NdisZeroMemory(ProtocolCB->TransportAddress, 6);
+ FillTransportBundleIndex(ProtocolCB->TransportAddress, BundleCB->hBundleHandle);
+
+ ProtocolCB->AdapterCB = AdapterCB;
+
+ Status = DoLineUpToProtocol(ProtocolCB);
+
+ } else {
+ Status = NDISWAN_ERROR_NO_ROUTE;
+ NdisWanDbgOut(DBG_FAILURE, DBG_PROTOCOL, ("Adapter not found!"));
+ }
+
+ NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("DoNewLineupToProtocols: Exit"));
+
+ return (Status);
+}
+
+NDIS_STATUS
+DoLineUpToProtocol(
+ IN PPROTOCOLCB ProtocolCB
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ NDIS_STATUS Status;
+ PDEFERRED_DESC DeferredDesc;
+ PADAPTERCB AdapterCB = ProtocolCB->AdapterCB;
+
+#if TRY_IMMEDIATE_LINEUP
+ if (NdisWanAcquireMiniportLock(AdapterCB)) {
+
+ NdisAcquireSpinLock(&AdapterCB->Lock);
+
+ if (IsDeferredQueueEmpty(&AdapterCB->DeferredQueue[StatusIndication])) {
+
+ NdisReleaseSpinLock(&AdapterCB->Lock);
+
+ Status = DoLineUpWork(ProtocolCB);
+
+ NdisWanReleaseMiniportLock(AdapterCB);
+
+ return (Status);
+ }
+
+ NdisReleaseSpinLock(&AdapterCB->Lock);
+
+ NdisWanReleaseMiniportLock(AdapterCB);
+ }
+#endif
+
+ NdisAcquireSpinLock(&AdapterCB->Lock);
+
+ //
+ // Queue up a deferred work item
+ //
+ NdisWanGetDeferredDesc(AdapterCB, &DeferredDesc);
+
+ DeferredDesc->Context = ProtocolCB;
+ DeferredDesc->Type = LineUp;
+
+ InsertTailDeferredQueue(&AdapterCB->DeferredQueue[StatusIndication],
+ DeferredDesc);
+
+ NdisWanSetDeferred(AdapterCB);
+
+ NdisReleaseSpinLock(&AdapterCB->Lock);
+
+ Status = NDIS_STATUS_PENDING;
+
+ return (Status);
+}
+
+NDIS_STATUS
+DoLineUpWork(
+ PPROTOCOLCB ProtocolCB
+ )
+{
+ ULONG i, AllocationSize;
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+ PNDIS_WAN_LINE_UP LineUpInfo;
+ PADAPTERCB AdapterCB = ProtocolCB->AdapterCB;
+ PBUNDLECB BundleCB = ProtocolCB->BundleCB;
+ PBUNDLE_LINE_UP BundleLineUpInfo = &BundleCB->LineUpInfo;
+
+ NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("DoLineupToProtocol: Enter"));
+
+ ASSERT(AdapterCB != NULL);
+
+ AllocationSize = sizeof(NDIS_WAN_LINE_UP) +
+ ProtocolCB->ulLineUpInfoLength +
+ (sizeof(WCHAR) * (MAX_NAME_LENGTH + 1) +
+ (2 * sizeof(PVOID)));
+
+ NdisWanAllocateMemory(&LineUpInfo, AllocationSize);
+
+ if (LineUpInfo != NULL) {
+ NDIS_HANDLE LineUpHandle = ProtocolCB->hTransportHandle;
+
+ //
+ // Fill values that are common to all protocols on this bundle
+ //
+ LineUpInfo->LinkSpeed = BundleLineUpInfo->BundleSpeed;
+ LineUpInfo->MaximumTotalSize = BundleLineUpInfo->ulMaximumTotalSize;
+ LineUpInfo->Quality = BundleLineUpInfo->Quality;
+ LineUpInfo->SendWindow = BundleLineUpInfo->usSendWindow;
+ LineUpInfo->ProtocolType = ProtocolCB->usProtocolType;
+ LineUpInfo->DeviceName.Length = 0;
+ LineUpInfo->DeviceName.MaximumLength = MAX_NAME_LENGTH + 1;
+ LineUpInfo->DeviceName.Buffer = (PWCHAR)((PUCHAR)LineUpInfo +
+ sizeof(NDIS_WAN_LINE_UP));
+ (ULONG)LineUpInfo->DeviceName.Buffer &= (ULONG)~(sizeof(PVOID) - 1);
+
+ LineUpInfo->ProtocolBuffer = (PUCHAR)LineUpInfo +
+ sizeof(NDIS_WAN_LINE_UP) +
+ (sizeof(WCHAR) * (MAX_NAME_LENGTH + 1) +
+ sizeof(PVOID));
+ (ULONG)LineUpInfo->ProtocolBuffer &= (ULONG)~(sizeof(PVOID) - 1);
+
+ //
+ // The Local address(SRC address in a send), is used
+ // to figure out what bundle to send across if the
+ // DEST address is a multicast. We use the two high
+ // order bytes of the address. The transport uses the
+ // other four bytes for a context on receive.
+ //
+ //
+ // The Remote address (DEST address in a send) is what we use to
+ // mutilplex sends across our single adapter/binding context.
+ // The address has the following format:
+ //
+ // XX XX XX YY YY ZZ
+ //
+ // XX = Randomly generated OUI
+ // YY = Index into the active bundle connection table to get bundlecb
+ // ZZ = Index into the protocol table of a bundle to get protocolcb
+ //
+ ETH_COPY_NETWORK_ADDRESS(LineUpInfo->RemoteAddress,ProtocolCB->NdisWanAddress);
+ ETH_COPY_NETWORK_ADDRESS(LineUpInfo->LocalAddress,ProtocolCB->TransportAddress);
+
+ //
+ // Fill in the protocol specific information
+ //
+ LineUpInfo->ProtocolBufferLength = ProtocolCB->ulLineUpInfoLength;
+ NdisMoveMemory(LineUpInfo->ProtocolBuffer,
+ ProtocolCB->LineUpInfo,
+ ProtocolCB->ulLineUpInfoLength);
+
+ //
+ // Do the line up indication
+ //
+ NdisMIndicateStatus(AdapterCB->hMiniportHandle,
+ NDIS_STATUS_WAN_LINE_UP,
+ LineUpInfo,
+ AllocationSize);
+
+ *((ULONG UNALIGNED *)(&LineUpHandle)) = *((ULONG UNALIGNED *)(&LineUpInfo->LocalAddress[2]));
+
+ //
+ // If this was the first line up for this protocolcb and
+ // this lineup was answered we need to collect some info
+ //
+ if (ProtocolCB->hTransportHandle == NULL) {
+
+ if (LineUpHandle != NULL) {
+
+ NdisAcquireSpinLock(&BundleCB->Lock);
+
+ ETH_COPY_NETWORK_ADDRESS(ProtocolCB->TransportAddress, LineUpInfo->LocalAddress);
+
+ ProtocolCB->hTransportHandle = LineUpHandle;
+
+ if (LineUpInfo->DeviceName.Length != 0) {
+ NdisWanStringToNdisString(&ProtocolCB->DeviceName,
+ LineUpInfo->DeviceName.Buffer);
+ }
+
+ NdisReleaseSpinLock(&BundleCB->Lock);
+
+ //
+ // If this is an nbf adapter
+ //
+ if (ProtocolCB->usProtocolType == PROTOCOL_NBF) {
+
+ ASSERT(AdapterCB->ProtocolType == PROTOCOL_NBF);
+
+ AdapterCB->NbfBundleCB = BundleCB;
+ AdapterCB->NbfProtocolHandle = ProtocolCB->hProtocolHandle;
+ }
+
+ } else {
+ Status = NDISWAN_ERROR_NO_ROUTE;
+ }
+ }
+
+ NdisWanFreeMemory(LineUpInfo);
+
+ } else {
+
+ Status = NDIS_STATUS_RESOURCES;
+ }
+
+ NdisWanDbgOut(DBG_TRACE, DBG_PROTOCOL, ("DoLineupToProtocol: Exit"));
+
+ return (Status);
+}
+
+NDIS_STATUS
+DoLineDownToProtocol(
+ PPROTOCOLCB ProtocolCB
+ )
+{
+ PADAPTERCB AdapterCB = ProtocolCB->AdapterCB;
+ PDEFERRED_DESC DeferredDesc;
+
+//
+// We are always going to defer the line down. This will
+// allow us to complete all sends and process all loopbacks
+// before doing the linedown.
+//
+ NdisAcquireSpinLock(&AdapterCB->Lock);
+
+ //
+ // Queue up a deferred work item
+ //
+ NdisWanGetDeferredDesc(AdapterCB, &DeferredDesc);
+
+ DeferredDesc->Context = ProtocolCB;
+ DeferredDesc->Type = LineDown;
+
+ InsertTailDeferredQueue(&AdapterCB->DeferredQueue[StatusIndication],
+ DeferredDesc);
+
+ NdisWanSetDeferred(AdapterCB);
+
+ NdisReleaseSpinLock(&AdapterCB->Lock);
+
+ return (NDIS_STATUS_PENDING);
+}
+
+NDIS_STATUS
+DoLineDownWork(
+ PPROTOCOLCB ProtocolCB
+ )
+{
+ NDIS_WAN_LINE_DOWN WanLineDown;
+ PNDIS_WAN_LINE_DOWN LineDownInfo = &WanLineDown;
+ PADAPTERCB AdapterCB = ProtocolCB->AdapterCB;
+
+ //
+ // The Remote address (DEST address) is what we use to mutilplex
+ // sends across our single adapter/binding context. The address
+ // has the following format:
+ //
+ // XX XX XX YY YY ZZ
+ //
+ // XX = Randomly generated OUI
+ // YY = Index into the active bundle connection table to get bundlecb
+ // ZZ = Index into the protocol table of a bundle to get protocolcb
+ //
+ ETH_COPY_NETWORK_ADDRESS(LineDownInfo->RemoteAddress, ProtocolCB->NdisWanAddress);
+ ETH_COPY_NETWORK_ADDRESS(LineDownInfo->LocalAddress, ProtocolCB->TransportAddress);
+
+ //
+ // If this is an nbf adapter
+ //
+ if (ProtocolCB->usProtocolType == PROTOCOL_NBF) {
+
+ ASSERT(AdapterCB->ProtocolType == PROTOCOL_NBF);
+
+ AdapterCB->NbfBundleCB = NULL;
+
+ (ULONG)AdapterCB->NbfProtocolHandle = MAX_PROTOCOLS + 1;
+ }
+
+ ProtocolCB->hTransportHandle = NULL;
+
+ NdisMIndicateStatus(AdapterCB->hMiniportHandle,
+ NDIS_STATUS_WAN_LINE_DOWN,
+ LineDownInfo,
+ sizeof(NDIS_WAN_LINE_DOWN));
+
+ return (NDIS_STATUS_SUCCESS);
+}
+
+VOID
+NdisWanProcessStatusIndications(
+ PADAPTERCB AdapterCB
+ )
+{
+ NDIS_STATUS Status;
+
+ while (!IsDeferredQueueEmpty(&AdapterCB->DeferredQueue[StatusIndication])) {
+ PPROTOCOLCB ProtocolCB;
+ PBUNDLECB BundleCB;
+ ULONG DescType;
+ PDEFERRED_DESC ReturnDesc;
+
+ ReturnDesc = RemoveHeadDeferredQueue(&AdapterCB->DeferredQueue[StatusIndication]);
+
+ NdisReleaseSpinLock(&AdapterCB->Lock);
+
+ ProtocolCB = ReturnDesc->Context;
+ BundleCB= ProtocolCB->BundleCB;
+ DescType = ReturnDesc->Type;
+
+ ASSERT((DescType == LineUp) || (DescType == LineDown));
+
+ if (DescType == LineUp) {
+ Status = DoLineUpWork(ProtocolCB);
+ }else {
+ Status = DoLineDownWork(ProtocolCB);
+ }
+
+ NdisAcquireSpinLock(&AdapterCB->Lock);
+
+ InsertHeadDeferredQueue(&AdapterCB->FreeDeferredQueue, ReturnDesc);
+
+ NdisAcquireSpinLock(&BundleCB->Lock);
+
+ BundleCB->IndicationStatus = Status;
+
+ NdisWanSetSyncEvent(&BundleCB->IndicationEvent);
+
+ NdisReleaseSpinLock(&BundleCB->Lock);
+ }
+}
diff --git a/private/ntos/ndis/ndiswan/receive.c b/private/ntos/ndis/ndiswan/receive.c
new file mode 100644
index 000000000..35652e39c
--- /dev/null
+++ b/private/ntos/ndis/ndiswan/receive.c
@@ -0,0 +1,2865 @@
+/*++
+
+Copyright (c) 1990-1995 Microsoft Corporation
+
+Module Name:
+
+ Receive.c
+
+Abstract:
+
+ This file contains the procedures for handling a receive indication from
+ a Wan Miniport link, bound to the lower interface of NdisWan, and passing
+ the data on to a protocol, bound to the upper interface of NdisWan. The
+ upper interface of NdisWan conforms to the NDIS 3.1 Miniport specification.
+ The lower interface of NdisWan conforms to the NDIS 3.1 Extentions for
+ Wan Miniport drivers.
+
+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"
+#include "compress.h"
+#include "isnipx.h"
+#include "nbfconst.h"
+#include "nbfhdrs.h"
+#include <rc4.h>
+
+VOID
+DoMultilinkProcessing(
+ PBUNDLECB BundleCB,
+ PRECV_DESC RecvDesc
+ );
+
+VOID
+UpdateMinRecvSeqNumber(
+ PBUNDLECB BundleCB
+ );
+
+VOID
+TryToAssembleFrame(
+ PBUNDLECB BundleCB
+ );
+
+VOID
+ProcessFrame(
+ PBUNDLECB BundleCB,
+ PRECV_DESC RecvDesc
+ );
+
+VOID
+QueueDeferredReceive(
+ PADAPTERCB AdapterCB,
+ PRECV_DESC RecvDesc
+ );
+
+BOOLEAN
+DoVJDecompression(
+ PBUNDLECB BundleCB,
+ USHORT ProtocolID,
+ PUCHAR *DataPointer,
+ PULONG DataLength,
+ PUCHAR Header,
+ PULONG HeaderLength
+ );
+
+BOOLEAN
+DoDecompDecryptProcessing(
+ PBUNDLECB BundleCB,
+ PLINKCB LinkCB,
+ PUCHAR *DataPointer,
+ PULONG DataLength
+ );
+
+VOID
+DoCompressionReset(
+ PBUNDLECB BundleCB
+ );
+
+VOID
+FlushRecvDescWindow(
+ PBUNDLECB BundleCB
+ );
+
+VOID
+NdisWanReturnRecvDesc(
+ PBUNDLECB BundleCB,
+ PRECV_DESC RecvDesc
+ );
+
+VOID
+FindHoleInRecvList(
+ PBUNDLECB BundleCB,
+ PRECV_DESC RecvDesc
+ );
+
+VOID
+NdisWanCopyFromBufferToPacket(
+ PUCHAR Buffer,
+ ULONG BytesToCopy,
+ PNDIS_PACKET NdisPacket,
+ ULONG PacketOffset,
+ PULONG BytesCopied
+ );
+
+#if 0
+ULONG
+CalculatePPPHeaderLength(
+ PLINKCB LinkCB
+ );
+#endif
+
+VOID
+QueuePromiscuousReceive(
+ PRECV_DESC RecvDesc
+ );
+
+#ifdef NT
+
+VOID
+CompleteIoRecvPacket(
+ PBUNDLECB BundleCB,
+ PLINKCB LinkCB,
+ USHORT PPPProtocolID,
+ PRECV_DESC RecvDesc
+ );
+
+#endif
+
+NDIS_STATUS
+NdisWanReceiveIndication(
+ NDIS_HANDLE NdisLinkContext,
+ PUCHAR Packet,
+ ULONG PacketSize
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ PLINKCB LinkCB;
+ PBUNDLECB BundleCB;
+ PRECV_DESC RecvDesc;
+ PUCHAR FramePointer;
+ ULONG FrameLength;
+ ULONG LinkFraming;
+
+ NdisWanDbgOut(DBG_TRACE, DBG_RECEIVE, ("NdisWanReceiveIndication: Enter"));
+
+ LINKCB_FROM_LINKH(LinkCB, NdisLinkContext);
+
+ if (LinkCB == NULL) {
+ return (NDIS_STATUS_SUCCESS);
+ }
+
+ BundleCB = LinkCB->BundleCB;
+
+ if (BundleCB == NULL) {
+ return (NDIS_STATUS_SUCCESS);
+ }
+
+ NdisAcquireSpinLock(&BundleCB->Lock);
+
+ if (LinkCB->State != LINK_UP ||
+ BundleCB->State != BUNDLE_UP) {
+
+ NdisReleaseSpinLock(&BundleCB->Lock);
+ return (NDIS_STATUS_SUCCESS);
+ }
+
+ //
+ // We need to get a descriptor to copy data into
+ //
+ NdisWanGetRecvDesc(BundleCB, &RecvDesc);
+
+ if (RecvDesc == NULL) {
+ NdisReleaseSpinLock(&BundleCB->Lock);
+ return (NDIS_STATUS_SUCCESS);
+ }
+
+ //
+ // Copy the data
+ //
+ NdisMoveMemory(RecvDesc->StartBuffer, Packet, PacketSize);
+ FramePointer = RecvDesc->CurrentBuffer = RecvDesc->StartBuffer;
+ FrameLength = RecvDesc->CurrentBufferLength = PacketSize;
+ RecvDesc->LinkCB = LinkCB;
+
+ //
+ // Add up the statistics
+ //
+ LinkCB->LinkStats.BytesReceived += PacketSize;
+ LinkCB->LinkStats.FramesReceived++;
+ BundleCB->BundleStats.BytesReceived += PacketSize;
+
+ //
+ // If we are in framing detect mode figure it out
+ //
+ if ((LinkFraming = LinkCB->LinkInfo.RecvFramingBits) == 0x00) {
+
+ if (*FramePointer == 0xFF && *(FramePointer + 1) == 0x03) {
+ LinkFraming =
+ LinkCB->LinkInfo.RecvFramingBits =
+ LinkCB->LinkInfo.SendFramingBits = PPP_FRAMING;
+ } else {
+ LinkFraming =
+ LinkCB->LinkInfo.RecvFramingBits =
+ LinkCB->LinkInfo.SendFramingBits = RAS_FRAMING;
+ }
+ }
+
+ if (BundleCB->FramingInfo.RecvFramingBits == 0x00) {
+ if (*FramePointer == 0xFF && *(FramePointer + 1) == 0x03) {
+ BundleCB->FramingInfo.RecvFramingBits =
+ BundleCB->FramingInfo.SendFramingBits = PPP_FRAMING;
+ } else {
+ BundleCB->FramingInfo.RecvFramingBits =
+ BundleCB->FramingInfo.SendFramingBits = RAS_FRAMING;
+ }
+ }
+
+ NdisReleaseSpinLock(&BundleCB->Lock);
+
+#if 0
+ if (FrameLength < CalculatePPPHeaderLength(LinkCB)) {
+
+ NdisWanDbgOut(DBG_FAILURE, DBG_RECEIVE, ("Receive buffer to small! %d", PacketSize));
+
+ return (NDIS_STATUS_SUCCESS);
+ }
+#endif
+
+ //
+ // If this is a PPP frame we will remove the link specific
+ // header information and check for multilink.
+ //
+ if (LinkFraming & PPP_FRAMING) {
+
+ //
+ // Remove the address/control part of the PPP header
+ //
+ if (*FramePointer == 0xFF) {
+ FramePointer += 2;
+ FrameLength -= 2;
+ }
+
+ //
+ // If multilink framing is set and this is a multilink frame
+ // send to the multilink processor!
+ //
+ if ((LinkFraming & PPP_MULTILINK_FRAMING) &&
+ ((*FramePointer == 0x3D) ||
+ (*FramePointer == 0x00) && (*(FramePointer + 1) == 0x3D)) ) {
+
+ //
+ // Remove multilink protocol id
+ //
+ if (*FramePointer & 1) {
+ FramePointer++;
+ FrameLength--;
+ } else {
+ FramePointer += 2;
+ FrameLength -= 2;
+ }
+
+ RecvDesc->CurrentBufferLength = FrameLength;
+ RecvDesc->CurrentBuffer = FramePointer;
+
+ DoMultilinkProcessing(BundleCB, RecvDesc);
+
+ return (NDIS_STATUS_SUCCESS);
+
+ } // end of PPP_MULTILINK_FRAMING
+
+ } // end of PPP_FRAMING
+
+ //
+ // Send the frame on for further processing!
+ //
+ RecvDesc->CurrentBufferLength = FrameLength;
+ RecvDesc->CurrentBuffer = FramePointer;
+
+ NdisAcquireSpinLock(&BundleCB->Lock);
+ ASSERT(!(BundleCB->Flags & IN_RECEIVE));
+ BundleCB->Flags |= IN_RECEIVE;
+ NdisReleaseSpinLock(&BundleCB->Lock);
+
+ ProcessFrame(BundleCB, RecvDesc);
+
+ NdisAcquireSpinLock(&BundleCB->Lock);
+ BundleCB->Flags &= ~IN_RECEIVE;
+ NdisReleaseSpinLock(&BundleCB->Lock);
+
+ NdisWanDbgOut(DBG_TRACE, DBG_RECEIVE, ("NdisWanReceiveIndication: Exit"));
+
+ return (NDIS_STATUS_SUCCESS);
+}
+
+VOID
+DoMultilinkProcessing(
+ PBUNDLECB BundleCB,
+ PRECV_DESC RecvDesc
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+ *DataPointer - Points to a pointer that points to a data block that
+ should have one of the following formats:
+
+ 0 1 2 3 4 5 6 7 8 9 1 1 1 1 1 1
+ 0 1 2 3 4 5
+ +-+-+-+-+------------------------+
+ Short Sequence Number |B|E|0|0| Sequence Number |
+ +-+-+-+-+------------------------+
+ | Data |
+ +--------------------------------+
+
+ +-+-+-+-+-+-+-+-+----------------+
+ Long Sequence Number |B|E|0|0|0|0|0|0|Sequence Number |
+ +-+-+-+-+-+-+-+-+----------------+
+ | Sequence Number |
+ +--------------------------------+
+ | Data |
+ +--------------------------------+
+
+Return Values:
+
+--*/
+{
+ BOOLEAN Inserted = FALSE;
+ ULONG BundleFraming;
+ PUCHAR FramePointer = RecvDesc->CurrentBuffer;
+ ULONG FrameLength = RecvDesc->CurrentBufferLength;
+ ULONG SequenceNumber, Flags;
+ PRECV_DESC RecvDescHole;
+ PLINKCB LinkCB = RecvDesc->LinkCB;
+
+ NdisAcquireSpinLock(&BundleCB->Lock);
+
+ BundleFraming = BundleCB->FramingInfo.RecvFramingBits;
+ RecvDescHole = BundleCB->RecvDescHole;
+
+ //
+ // Get the flags
+ //
+ Flags = *FramePointer & MULTILINK_FLAG_MASK;
+
+ //
+ // Get the sequence number
+ //
+ if (BundleFraming & PPP_SHORT_SEQUENCE_HDR_FORMAT) {
+ //
+ // Short sequence format
+ //
+ SequenceNumber = ((*FramePointer & 0x0F) << 8) | *(FramePointer + 1);
+
+ FramePointer += 2;
+ FrameLength -= 2;
+
+ } else {
+ //
+ // Long sequence format
+ //
+ SequenceNumber = (*(FramePointer + 1) << 16) |
+ (*(FramePointer + 2) << 8) |
+ *(FramePointer + 3);
+
+ FramePointer += 4;
+ FrameLength -= 4;
+ }
+
+ NdisWanDbgOut(DBG_INFO, DBG_MULTILINK_RECV,
+ ("r %8.8x %8.8x h: %8.8x l: %d",SequenceNumber, Flags, RecvDescHole->SequenceNumber, LinkCB->hLinkHandle));
+
+ //
+ // Is the new recveive sequence number smaller that the last
+ // sequence number received on this link? If so the increasing seq
+ // number rule has been violated and we need to toss this one.
+ //
+ if (SEQ_LT(SequenceNumber,
+ LinkCB->LastRecvSeqNumber,
+ BundleCB->RecvSeqTest)) {
+
+ ASSERT(RecvDesc->RefCount == 1);
+
+ LinkCB->RecvFragmentsLost++;
+ BundleCB->RecvFragmentsLost++;
+
+ NdisWanDbgOut(DBG_FAILURE, DBG_MULTILINK_RECV,
+ ("dl s: %8.8x %8.8x lr: %8.8x", SequenceNumber, Flags,
+ LinkCB->LastRecvSeqNumber));
+
+ NdisWanReturnRecvDesc(BundleCB, RecvDesc);
+
+ NdisReleaseSpinLock(&BundleCB->Lock);
+
+ return;
+
+ }
+
+ //
+ // Initialize the recv desc
+ //
+ RecvDesc->Flags = Flags;
+ RecvDesc->SequenceNumber =
+ LinkCB->LastRecvSeqNumber = SequenceNumber;
+ RecvDesc->CurrentBufferLength = FrameLength;
+ RecvDesc->CurrentBuffer = FramePointer;
+
+ //
+ // Is the new receive sequence number smaller than the hole? If so
+ // we received a fragment across a slow link after it has been flushed
+ //
+ if (SEQ_LT(SequenceNumber,
+ RecvDescHole->SequenceNumber,
+ BundleCB->RecvSeqTest)) {
+ ASSERT(RecvDesc->RefCount == 1);
+
+ LinkCB->RecvFragmentsLost++;
+ BundleCB->RecvFragmentsLost++;
+
+ NdisWanDbgOut(DBG_FAILURE, DBG_MULTILINK_RECV,
+ ("db s: %8.8x %8.8x h: %8.8x", SequenceNumber, Flags,
+ RecvDescHole->SequenceNumber));
+
+ NdisWanReturnRecvDesc(BundleCB, RecvDesc);
+
+ NdisReleaseSpinLock(&BundleCB->Lock);
+
+ return;
+ }
+
+ //
+ // If this fills the hole
+ //
+ if (SEQ_EQ(SequenceNumber, RecvDescHole->SequenceNumber)) {
+
+ //
+ // Insert the hole filler in the current holes spot
+ //
+ RecvDesc->Linkage.Blink = (PLIST_ENTRY)RecvDescHole->Linkage.Blink;
+ RecvDesc->Linkage.Flink = (PLIST_ENTRY)RecvDescHole->Linkage.Flink;
+
+ RecvDesc->Linkage.Blink->Flink =
+ RecvDesc->Linkage.Flink->Blink = (PLIST_ENTRY)RecvDesc;
+
+ //
+ // Find the next hole
+ //
+ FindHoleInRecvList(BundleCB, RecvDesc);
+
+ NdisWanDbgOut(DBG_INFO, DBG_MULTILINK_RECV, ("r1"));
+
+ } else {
+
+ PRECV_DESC BeginDesc, EndDesc;
+
+ //
+ // This does not fill a hole so we need to insert it into
+ // the list at the right spot. This spot will be someplace
+ // between the hole and the end of the list.
+ //
+ BeginDesc = RecvDescHole;
+ EndDesc = (PRECV_DESC)BeginDesc->Linkage.Flink;
+
+ while ((PVOID)EndDesc != (PVOID)&BundleCB->RecvDescAssemblyList) {
+
+ //
+ // Calculate the absolute delta between the begining sequence
+ // number and the sequence number we are looking to insert.
+ //
+ ULONG DeltaBegin =
+ ((RecvDesc->SequenceNumber - BeginDesc->SequenceNumber) &
+ BundleCB->RecvSeqMask);
+
+ //
+ // Calculate the absolute delta between the begining sequence
+ // number and the end sequence number.
+ //
+ ULONG DeltaEnd =
+ ((EndDesc->SequenceNumber - BeginDesc->SequenceNumber) &
+ BundleCB->RecvSeqMask);
+
+ //
+ // If the delta from the begin to current is less than
+ // the delta from the end to current it is time to insert
+ //
+ if (DeltaBegin < DeltaEnd) {
+ PLIST_ENTRY Flink, Blink;
+
+ //
+ // Insert the desc
+ //
+ RecvDesc->Linkage.Flink = (PLIST_ENTRY)EndDesc;
+ RecvDesc->Linkage.Blink = (PLIST_ENTRY)BeginDesc;
+ BeginDesc->Linkage.Flink =
+ EndDesc->Linkage.Blink = (PLIST_ENTRY)RecvDesc;
+
+ Inserted = TRUE;
+
+ NdisWanDbgOut(DBG_INFO, DBG_MULTILINK_RECV, ("r2"));
+
+ break;
+
+ } else {
+
+ //
+ // Get next pair of descriptors
+ //
+ BeginDesc = EndDesc;
+ EndDesc = (PRECV_DESC)EndDesc->Linkage.Flink;
+ }
+ }
+
+ if (!Inserted) {
+
+ //
+ // If we are here we have fallen through and we need to
+ // add this at the end of the list
+ //
+ InsertTailList(&BundleCB->RecvDescAssemblyList, &RecvDesc->Linkage);
+
+ NdisWanDbgOut(DBG_INFO, DBG_MULTILINK_RECV, ("r3"));
+ }
+ }
+
+ //
+ // Update the bundles minimum recv sequence number. This is
+ // used to detect lost fragments.
+ //
+ UpdateMinRecvSeqNumber(BundleCB);
+
+ //
+ // Check for lost fragments. If the minimum recv sequence number
+ // over the bundle is greater than the hole sequence number we have
+ // lost a fragment and need to flush the assembly list until we find
+ // the first begin fragment after the hole.
+ //
+ if (SEQ_GT(BundleCB->MinReceivedSeqNumber,
+ RecvDescHole->SequenceNumber,
+ BundleCB->RecvSeqTest)) {
+
+ NdisWanDbgOut(DBG_FAILURE, DBG_MULTILINK_RECV,
+ ("min %8.8x > h %8.8x b %8.8x", BundleCB->MinReceivedSeqNumber,
+ RecvDescHole->SequenceNumber, BundleCB));
+
+ //
+ // Flush the recv desc assembly window.
+ //
+ FlushRecvDescWindow(BundleCB);
+
+ }
+
+ //
+ // See if we can complete some frames!!!!
+ //
+ TryToAssembleFrame(BundleCB);
+
+ NdisReleaseSpinLock(&BundleCB->Lock);
+}
+
+VOID
+UpdateMinRecvSeqNumber(
+ PBUNDLECB BundleCB
+ )
+{
+ PLINKCB LinkCB = (PLINKCB)BundleCB->LinkCBList.Flink;
+
+ NdisWanDbgOut(DBG_INFO, DBG_MULTILINK_RECV,
+ ("MinReceived c %8.8x", BundleCB->MinReceivedSeqNumber));
+
+ BundleCB->MinReceivedSeqNumber = LinkCB->LastRecvSeqNumber;
+
+ for (LinkCB = (PLINKCB)LinkCB->Linkage.Flink;
+ (PVOID)LinkCB != (PVOID)&BundleCB->LinkCBList;
+ LinkCB = (PLINKCB)LinkCB->Linkage.Flink) {
+
+ if (SEQ_LT(LinkCB->LastRecvSeqNumber,
+ BundleCB->MinReceivedSeqNumber,
+ BundleCB->RecvSeqTest)) {
+ BundleCB->MinReceivedSeqNumber = LinkCB->LastRecvSeqNumber;
+ }
+ }
+
+ NdisWanDbgOut(DBG_INFO, DBG_MULTILINK_RECV,
+ ("MinReceived n %8.8x", BundleCB->MinReceivedSeqNumber));
+}
+
+VOID
+FindHoleInRecvList(
+ PBUNDLECB BundleCB,
+ PRECV_DESC RecvDesc
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+ We want to start at the spot where the current hole was removed
+ from and look for adjoining recv desc's in the list who have
+ sequence numbers that differ by more than 1.
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ PRECV_DESC NextRecvDesc, RecvDescHole;
+ ULONG SequenceNumber;
+ PLIST_ENTRY RecvList;
+
+ RecvDescHole = BundleCB->RecvDescHole;
+
+ RecvList = &BundleCB->RecvDescAssemblyList;
+
+ NdisWanDbgOut(DBG_INFO, DBG_MULTILINK_RECV,
+ ("h: %8.8x", RecvDescHole->SequenceNumber));
+
+ if (IsListEmpty(RecvList)) {
+ //
+ // Set the new sequence number
+ //
+ RecvDescHole->SequenceNumber += 1;
+ RecvDescHole->SequenceNumber &= BundleCB->RecvSeqMask;
+
+ //
+ // Put the hole back on the list
+ //
+ InsertHeadList(RecvList, &RecvDescHole->Linkage);
+
+ } else {
+
+ //
+ // Walk the list looking for two descriptors that have
+ // sequence numbers differing by more than 1 or until we
+ // get to the end of the list
+ //
+ NextRecvDesc = (PRECV_DESC)RecvDesc->Linkage.Flink;
+ SequenceNumber = RecvDesc->SequenceNumber;
+
+ while (((PVOID)NextRecvDesc != (PVOID)RecvList) &&
+ (((NextRecvDesc->SequenceNumber - RecvDesc->SequenceNumber) &
+ BundleCB->RecvSeqMask) == 1)) {
+
+ RecvDesc = NextRecvDesc;
+ NextRecvDesc = (PRECV_DESC)RecvDesc->Linkage.Flink;
+ SequenceNumber = RecvDesc->SequenceNumber;
+ }
+
+ RecvDescHole->SequenceNumber = SequenceNumber + 1;
+ RecvDescHole->SequenceNumber &= BundleCB->RecvSeqMask;
+
+ RecvDescHole->Linkage.Flink = (PLIST_ENTRY)NextRecvDesc;
+ RecvDescHole->Linkage.Blink = (PLIST_ENTRY)RecvDesc;
+
+ RecvDesc->Linkage.Flink =
+ NextRecvDesc->Linkage.Blink =
+ (PLIST_ENTRY)RecvDescHole;
+ }
+
+ NdisWanDbgOut(DBG_INFO, DBG_MULTILINK_RECV, ("nh: %8.8x", RecvDescHole->SequenceNumber));
+}
+
+VOID
+NdisWanGetRecvDesc(
+ PBUNDLECB BundleCB,
+ PRECV_DESC *ReturnRecvDesc
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ PRECV_DESC RecvDesc = NULL;
+ ULONG i;
+
+ //
+ // Try the local pool first
+ //
+ if (BundleCB != NULL
+ && !IsListEmpty(&BundleCB->RecvDescPool)) {
+
+ RecvDesc = (PRECV_DESC)RemoveHeadList(&BundleCB->RecvDescPool);
+ BundleCB->RecvDescCount--;
+
+ } else {
+
+ //
+ // Since the local pool is empty we will
+ // try to get a desc from the global pool
+ //
+ // MAX_MRRU -> Data packet
+ // 14 -> Ethernet Header
+ // 128 -> Used for VJ header compression
+ // 3 * sizeof(PVOID) -> DWORD alignment
+
+ if (IsListEmpty(&GlobalRecvDescPool.List)) {
+
+ ULONG AllocationSize = sizeof(RECV_DESC) +
+ MAX_MRRU + 14 + 128 + 3 * sizeof(PVOID);
+
+ for (i = 0; i < 10; i++) {
+
+ //
+ // The global list is empty so we need to allocate
+ // some more
+ //
+ NdisWanAllocateMemory(&RecvDesc, AllocationSize);
+
+ if (RecvDesc != NULL) {
+
+ RecvDesc->AllocationSize = AllocationSize;
+
+ RecvDesc->WanHeader = (PUCHAR)RecvDesc + sizeof(RECV_DESC) + sizeof(PVOID);
+ (ULONG)RecvDesc->WanHeader &= (ULONG)~(sizeof(PVOID) - 1);
+
+ RecvDesc->LookAhead = RecvDesc->WanHeader + 14 + sizeof(PVOID);
+ (ULONG)RecvDesc->LookAhead &= (ULONG)~(sizeof(PVOID) - 1);
+
+ RecvDesc->StartBuffer = RecvDesc->LookAhead + 128 + sizeof(PVOID);
+ (ULONG)RecvDesc->StartBuffer &= (ULONG)~(sizeof(PVOID) - 1);
+
+ RecvDesc->CurrentBuffer = RecvDesc->StartBuffer;
+
+ NdisWanInterlockedInsertTailList(&GlobalRecvDescPool.List,
+ &RecvDesc->Linkage,
+ &GlobalRecvDescPool.Lock.SpinLock);
+
+ NdisWanInterlockedInc(&GlobalRecvDescPool.ulCount);
+
+ } else {
+
+ //
+ // Memory allocation failed!
+ //
+ break;
+ }
+ }
+
+ }
+
+ if (!IsListEmpty(&GlobalRecvDescPool.List)) {
+
+ RecvDesc =
+ (PRECV_DESC)NdisWanInterlockedRemoveHeadList(&GlobalRecvDescPool.List,
+ &GlobalRecvDescPool.Lock.SpinLock);
+
+ NdisWanInterlockedDec(&GlobalRecvDescPool.ulCount);
+
+ RecvDesc->BundleCB = BundleCB;
+ }
+
+ }
+
+ if (RecvDesc) {
+ ASSERT(RecvDesc->RefCount == 0);
+ NdisWanInterlockedInc(&RecvDesc->RefCount);
+ }
+
+ *ReturnRecvDesc = RecvDesc;
+}
+
+VOID
+NdisWanReturnRecvDesc(
+ PBUNDLECB BundleCB,
+ PRECV_DESC RecvDesc
+ )
+{
+ if (NdisWanInterlockedDec(&RecvDesc->RefCount) == 0) {
+
+ if (BundleCB->State == BUNDLE_UP &&
+ BundleCB->RecvDescCount < BundleCB->RecvDescMax) {
+ //
+ // Return receive descriptor to bundle list
+ //
+ InsertTailList(&BundleCB->RecvDescPool, &RecvDesc->Linkage);
+ BundleCB->RecvDescCount++;
+
+ } else {
+ //
+ // Return receive descriptor to global list
+ //
+ NdisWanInterlockedInsertTailList(&GlobalRecvDescPool.List,
+ &RecvDesc->Linkage,
+ &GlobalRecvDescPool.Lock.SpinLock);
+ NdisWanInterlockedInc(&GlobalRecvDescPool.ulCount);
+
+ }
+ }
+}
+
+
+VOID
+FlushRecvDescWindow(
+ IN PBUNDLECB BundleCB
+ )
+/*++
+
+Routine Name:
+
+ FlushRecvDescWindow
+
+Routine Description:
+
+ This routine is called to flush recv desc's from the assembly list when
+ a fragment loss is detected. The idea is to flush fragments until we find
+ a begin fragment that has a sequence number >= the minimum received fragment
+ on the bundle.
+
+Arguments:
+
+--*/
+{
+ PRECV_DESC RecvDescHole = BundleCB->RecvDescHole;
+ PRECV_DESC TempDesc;
+ ULONG Flags;
+
+ //
+ // Remove all recvdesc's until we find the hole
+ //
+ while (!IsListEmpty(&BundleCB->RecvDescAssemblyList)) {
+
+ TempDesc = (PRECV_DESC)RemoveHeadList(&BundleCB->RecvDescAssemblyList);
+
+ if (TempDesc == RecvDescHole) {
+ break;
+ }
+
+ BundleCB->RecvFragmentsLost++;
+ TempDesc->LinkCB->RecvFragmentsLost++;
+
+ NdisWanDbgOut(DBG_FAILURE, DBG_MULTILINK_RECV,
+ ("flw %8.8x %8.8x h: %8.8x", TempDesc->SequenceNumber,
+ TempDesc->Flags, RecvDescHole->SequenceNumber));
+
+ NdisWanReturnRecvDesc(BundleCB, TempDesc);
+ }
+
+ //
+ // Now flush all recvdesc's until we find a begin fragment that has a
+ // sequence number >= M or the list is empty.
+ //
+ while (!IsListEmpty(&BundleCB->RecvDescAssemblyList)) {
+
+ TempDesc = (PRECV_DESC)BundleCB->RecvDescAssemblyList.Flink;
+ Flags = TempDesc->Flags;
+
+ if (TempDesc->Flags & MULTILINK_BEGIN_FRAME) {
+ break;
+ }
+
+ BundleCB->RecvFragmentsLost++;
+ TempDesc->LinkCB->RecvFragmentsLost++;
+
+ NdisWanDbgOut(DBG_FAILURE, DBG_MULTILINK_RECV,
+ ("flw %8.8x %8.8x h: %8.8x", TempDesc->SequenceNumber,
+ TempDesc->Flags, RecvDescHole->SequenceNumber));
+
+ RecvDescHole->SequenceNumber = TempDesc->SequenceNumber;
+
+ RemoveEntryList(&TempDesc->Linkage);
+ NdisWanReturnRecvDesc(BundleCB, TempDesc);
+ TempDesc == NULL;
+ }
+
+ //
+ // Now reinsert the hole desc.
+ //
+ NdisWanDbgOut(DBG_FAILURE, DBG_MULTILINK_RECV,
+ ("h: %8.8x", RecvDescHole->SequenceNumber));
+
+ FindHoleInRecvList(BundleCB, TempDesc);
+
+ NdisWanDbgOut(DBG_FAILURE, DBG_MULTILINK_RECV,
+ ("nh: %8.8x", RecvDescHole->SequenceNumber));
+}
+
+VOID
+FlushRecvDescAssemblyList(
+ IN PBUNDLECB BundleCB
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ PRECV_DESC RecvDesc;
+
+ while (!IsListEmpty(&BundleCB->RecvDescAssemblyList)) {
+
+ RecvDesc = (PRECV_DESC)RemoveHeadList(&BundleCB->RecvDescAssemblyList);
+
+ NdisWanReturnRecvDesc(BundleCB, RecvDesc);
+ }
+}
+
+VOID
+FreeRecvDescFreeList(
+ IN PBUNDLECB BundleCB
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ PRECV_DESC RecvDesc;
+
+ while (!IsListEmpty(&BundleCB->RecvDescPool)) {
+
+ RecvDesc = (PRECV_DESC)RemoveHeadList(&BundleCB->RecvDescPool);
+
+ NdisWanInterlockedInsertTailList(&GlobalRecvDescPool.List,
+ &RecvDesc->Linkage,
+ &GlobalRecvDescPool.Lock.SpinLock);
+
+ NdisWanInterlockedInc(&GlobalRecvDescPool.ulCount);
+
+ }
+}
+
+VOID
+TryToAssembleFrame(
+ PBUNDLECB BundleCB
+ )
+/*++
+
+Routine Name:
+
+ TryToAssembleFrame
+
+Routine Description:
+
+ The goal here is to walk the recv list looking for a full frame
+ (BeginFlag, EndFlag, no holes in between). If we do not have a
+ full frame we return FALSE.
+
+ If we have a full frame we remove each desc from the assembly list
+ copying the data into the first desc and returning all of the desc's
+ except the first one to the free pool. Once all of the data had been
+ collected we process the frame. After the frame has been processed
+ we return the first desc to the free pool.
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ PRECV_DESC RecvDesc, RecvDescHole;
+ ULONG MaxRRecvFrameSize;
+ PUCHAR DataPointer;
+
+ RecvDesc = (PRECV_DESC)BundleCB->RecvDescAssemblyList.Flink;
+ RecvDescHole = BundleCB->RecvDescHole;
+
+ //
+ // If we are already doing some receive processing get out.
+ //
+ if (BundleCB->Flags & IN_RECEIVE) {
+ return;
+ }
+
+TryToAssembleAgain:
+
+ while ((RecvDesc != RecvDescHole) &&
+ (RecvDesc->Flags & MULTILINK_BEGIN_FRAME)) {
+
+ PRECV_DESC NextRecvDesc = (PRECV_DESC)RecvDesc->Linkage.Flink;
+
+ MaxRRecvFrameSize = BundleCB->FramingInfo.MaxRRecvFrameSize;
+
+ DataPointer = RecvDesc->CurrentBuffer + RecvDesc->CurrentBufferLength;
+
+ while ((NextRecvDesc != RecvDescHole) &&
+ !(RecvDesc->Flags & MULTILINK_END_FRAME)) {
+
+ RemoveEntryList(&NextRecvDesc->Linkage);
+
+ ASSERT(NextRecvDesc != RecvDescHole);
+ ASSERT(RecvDesc != RecvDescHole);
+
+ NdisWanDbgOut(DBG_INFO, DBG_MULTILINK_RECV, ("c 0x%8.8x -> 0x%8.8x",
+ NextRecvDesc->SequenceNumber, RecvDesc->SequenceNumber));
+
+ NdisWanDbgOut(DBG_INFO, DBG_MULTILINK_RECV, ("fl 0x%8.8x -> 0x%8.8x",
+ NextRecvDesc->Flags, RecvDesc->Flags));
+
+ NdisWanDbgOut(DBG_INFO, DBG_MULTILINK_RECV, ("l %d -> %d",
+ NextRecvDesc->CurrentBufferLength, RecvDesc->CurrentBufferLength));
+
+ //
+ // Update recvdesc info
+ //
+ RecvDesc->Flags |= NextRecvDesc->Flags;
+ RecvDesc->SequenceNumber = NextRecvDesc->SequenceNumber;
+ RecvDesc->CurrentBufferLength += NextRecvDesc->CurrentBufferLength;
+
+ //
+ // Make sure we don't assemble something too big!
+ //
+ if (RecvDesc->CurrentBufferLength > MaxRRecvFrameSize) {
+
+ NdisWanDbgOut(DBG_FAILURE, DBG_MULTILINK_RECV,
+ ("Max receive size exceeded!"));
+
+ //
+ // Return the recv desc's
+ //
+ RemoveEntryList(&RecvDesc->Linkage);
+
+ BundleCB->RecvFragmentsLost += 2;
+ RecvDesc->LinkCB->RecvFragmentsLost += 2;
+
+ NdisWanDbgOut(DBG_FAILURE, DBG_MULTILINK_RECV,
+ ("dumping %8.8x %8.8x h: %8.8x", RecvDesc->SequenceNumber,
+ RecvDesc->Flags, RecvDescHole->SequenceNumber));
+
+ NdisWanReturnRecvDesc(BundleCB, RecvDesc);
+
+ NdisWanDbgOut(DBG_FAILURE, DBG_MULTILINK_RECV,
+ ("dumping %8.8x %8.8x h: %8.8x", NextRecvDesc->SequenceNumber,
+ NextRecvDesc->Flags, RecvDescHole->SequenceNumber));
+
+ NdisWanReturnRecvDesc(BundleCB, NextRecvDesc);
+
+ //
+ // Start at the list head and flush until we find either the hole
+ // or a new begin fragment.
+ //
+ RecvDesc = (PRECV_DESC)BundleCB->RecvDescAssemblyList.Flink;
+
+ while (RecvDesc != RecvDescHole &&
+ !(RecvDesc->Flags & MULTILINK_BEGIN_FRAME)) {
+
+ RemoveHeadList(&BundleCB->RecvDescAssemblyList);
+
+ BundleCB->RecvFragmentsLost += 1;
+ RecvDesc->LinkCB->RecvFragmentsLost += 1;
+
+ NdisWanDbgOut(DBG_FAILURE, DBG_MULTILINK_RECV,
+ ("dumping %8.8x %8.8x h: %8.8x", RecvDesc->SequenceNumber,
+ RecvDesc->Flags, RecvDescHole->SequenceNumber));
+
+ NdisWanReturnRecvDesc(BundleCB, RecvDesc);
+ }
+
+ goto TryToAssembleAgain;
+ }
+
+ NdisMoveMemory(DataPointer,
+ NextRecvDesc->CurrentBuffer,
+ NextRecvDesc->CurrentBufferLength);
+
+ DataPointer += NextRecvDesc->CurrentBufferLength;
+
+ NdisWanReturnRecvDesc(BundleCB, NextRecvDesc);
+
+ NextRecvDesc = (PRECV_DESC)RecvDesc->Linkage.Flink;
+ }
+
+ //
+ // We hit a hole before completion of the frame.
+ // Get out.
+ //
+ if (!IsCompleteFrame(RecvDesc->Flags)) {
+ return;
+ }
+
+ //
+ // If we made it here we must have a begin flag, end flag, and
+ // no hole in between. Let's build a frame.
+ //
+ RecvDesc = (PRECV_DESC)RemoveHeadList(&BundleCB->RecvDescAssemblyList);
+
+ NdisWanDbgOut(DBG_INFO, DBG_MULTILINK_RECV, ("a %8.8x %8.8x", RecvDesc->SequenceNumber, RecvDesc->Flags));
+
+ RecvDesc->LinkCB = NULL;
+
+ BundleCB->Flags |= IN_RECEIVE;
+
+ NdisReleaseSpinLock(&BundleCB->Lock);
+
+ ProcessFrame(BundleCB, RecvDesc);
+
+ NdisAcquireSpinLock(&BundleCB->Lock);
+
+ BundleCB->Flags &= ~IN_RECEIVE;
+
+ RecvDesc = (PRECV_DESC)BundleCB->RecvDescAssemblyList.Flink;
+
+ } // end of while MULTILINK_BEGIN_FRAME
+}
+
+VOID
+ProcessFrame(
+ PBUNDLECB BundleCB,
+ PRECV_DESC RecvDesc
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ PPROTOCOLCB ProtocolCB = NULL;
+ PADAPTERCB AdapterCB;
+ PLINKCB LinkCB;
+ PUCHAR FramePointer;
+ ULONG BundleFraming, FrameLength;
+ PWAN_STATS BundleStats;
+ USHORT PPPProtocolID = 0;
+ ULONG i, LookAheadLength = 0;
+ ULONG TotalLength;
+ PUCHAR WanHeader;
+ PUCHAR LookAhead;
+ NDISWAN_RECV_CONTEXT ReceiveContext;
+
+ NdisWanDbgOut(DBG_TRACE, DBG_RECEIVE, ("ProcessFrame: Enter"));
+
+ //
+ // We do not have an active link or we have a zero
+ // length packet, so drop the receive.
+ //
+ if (BundleCB->State != BUNDLE_UP ||
+ RecvDesc->CurrentBufferLength == 0) {
+ goto PROCESS_FRAME_EXIT;
+ }
+
+ LinkCB = (RecvDesc->LinkCB == NULL) ?
+ (PLINKCB)BundleCB->LinkCBList.Flink : RecvDesc->LinkCB;
+
+ FramePointer = RecvDesc->CurrentBuffer;
+ FrameLength = RecvDesc->CurrentBufferLength;
+ WanHeader = RecvDesc->WanHeader;
+ LookAhead = RecvDesc->LookAhead;
+
+ BundleFraming = BundleCB->FramingInfo.RecvFramingBits;
+ BundleStats = &BundleCB->BundleStats;
+
+ BundleStats->FramesReceived++;
+
+ if (BundleFraming & PPP_FRAMING) {
+
+ //
+ // Get the PPP Protocol id
+ // 0xC1 is SPAP - Shiva hack!
+ //
+ if ((*FramePointer & 1) &&
+ (*FramePointer != 0xC1) &&
+ (*FramePointer != 0xCF)) {
+
+ //
+ // Field is compressed
+ //
+ PPPProtocolID = *FramePointer;
+ FramePointer++;
+ FrameLength--;
+
+ } else {
+
+ //
+ // Field is not compressed
+ //
+ PPPProtocolID = (*FramePointer << 8) | *(FramePointer + 1);
+ FramePointer += 2;
+ FrameLength -= 2;
+
+ }
+
+ //
+ // Is this a compressed frame?
+ //
+ if (PPPProtocolID == PPP_PROTOCOL_COMPRESSION) {
+
+ if (!DoDecompDecryptProcessing(BundleCB,
+ LinkCB,
+ &FramePointer,
+ &FrameLength)){
+
+ goto PROCESS_FRAME_EXIT;
+ }
+
+ //
+ // Get the new PPPProtocolID
+ //
+ if (*FramePointer & 1) {
+
+ //
+ // Field is compressed
+ //
+ PPPProtocolID = *FramePointer;
+ FramePointer++;
+ FrameLength--;
+
+ } else {
+ PPPProtocolID = (*FramePointer << 8) | *(FramePointer + 1);
+ FramePointer += 2;
+ FrameLength -= 2;
+
+ }
+
+ //end of PPP_PROTOCOL_COMPRESSED
+ } else if ((PPPProtocolID == PPP_PROTOCOL_COMP_RESET) &&
+ (*FramePointer == 14)) {
+
+ if (NdisWanCB.PromiscuousAdapter != NULL) {
+ RecvDesc->LookAheadLength = 0;
+ RecvDesc->WanHeader[0] =
+ RecvDesc->WanHeader[6] = ' ';
+ RecvDesc->WanHeader[1] =
+ RecvDesc->WanHeader[7] = 'R';
+ RecvDesc->WanHeader[2] =
+ RecvDesc->WanHeader[8] = 'E';
+ RecvDesc->WanHeader[3] =
+ RecvDesc->WanHeader[9] = 'C';
+ RecvDesc->WanHeader[4] =
+ RecvDesc->WanHeader[10] = 'V';
+ RecvDesc->WanHeader[5] =
+ RecvDesc->WanHeader[11] = (UCHAR)LinkCB->hLinkHandle;
+ RecvDesc->WanHeader[12] = (UCHAR)(PPPProtocolID >> 8);
+ RecvDesc->WanHeader[13] = (UCHAR)PPPProtocolID;
+ RecvDesc->WanHeaderLength = 14;
+ RecvDesc->CurrentBuffer = FramePointer;
+ RecvDesc->CurrentBufferLength = FrameLength;
+
+ //
+ // Queue the packet on the promiscous adapter
+ //
+ QueuePromiscuousReceive(RecvDesc);
+ }
+
+ //
+ // Compression reset!
+ //
+ DoCompressionReset(BundleCB);
+
+ goto PROCESS_FRAME_EXIT;
+
+ } // end of compression reset
+
+ // end of PPP_FRAMING
+ } else {
+
+ if (BundleFraming & RAS_FRAMING) {
+
+ //
+ // Must be RAS framing
+ //
+
+ // For normal NBF frames, first byte is always the DSAP
+ // i.e 0xF0 followed by SSAP 0xF0 or 0xF1
+ //
+ //
+ if (*FramePointer == 14) {
+
+ //
+ // Compression reset!
+ //
+ DoCompressionReset(BundleCB);
+
+ goto PROCESS_FRAME_EXIT;
+ }
+
+ if (*FramePointer == 0xFD) {
+
+ //
+ // Skip over 0xFD
+ //
+ FramePointer++;
+ FrameLength--;
+
+ //
+ // Decompress as if an NBF PPP Packet
+ //
+ if (!DoDecompDecryptProcessing(BundleCB,
+ LinkCB,
+ &FramePointer,
+ &FrameLength)){
+ //
+ // There was an error get out!
+ //
+ goto PROCESS_FRAME_EXIT;
+ }
+ }
+
+ //
+ // Make frame look like an NBF PPP packet
+ //
+ PPPProtocolID = PPP_PROTOCOL_NBF;
+
+ } // end of RAS framing
+
+ } // end of non-ppp framing
+
+ //
+ // If this is slip or if the ProtocolID == PPP_PROTOCOL_COMPRESSED_TCP ||
+ // ProtocolID == PPP_PROTOCOL_UNCOMPRESSED_TCP
+ //
+ if ((BundleFraming & SLIP_FRAMING) ||
+ ((PPPProtocolID == PPP_PROTOCOL_COMPRESSED_TCP) ||
+ (PPPProtocolID == PPP_PROTOCOL_UNCOMPRESSED_TCP))) {
+
+ if (!DoVJDecompression(BundleCB, // Bundle
+ PPPProtocolID, // ProtocolID
+ &FramePointer, // Input buffer
+ &FrameLength, // Input length
+ LookAhead, // Output buffer
+ &LookAheadLength)) {
+
+ goto PROCESS_FRAME_EXIT;
+
+ }
+
+
+ PPPProtocolID = PPP_PROTOCOL_IP;
+
+
+ // end of check for VJ header compression
+ }
+
+ if ((PPPProtocolID >= 0x8000) ||
+ (BundleCB->ulNumberOfRoutes == 1)) {
+
+ RecvDesc->CurrentBufferLength = FrameLength;
+ RecvDesc->CurrentBuffer = FramePointer;
+
+ //
+ // Either this frame is an LCP, NCP or we have no routes yet.
+ // Indicate to PPP engine.
+ //
+ CompleteIoRecvPacket(BundleCB,
+ LinkCB,
+ PPPProtocolID,
+ RecvDesc);
+
+ goto PROCESS_FRAME_EXIT;
+ }
+
+ //
+ // We need to find a protocol to indicate this frame to.
+ //
+
+ NdisAcquireSpinLock(&BundleCB->Lock);
+
+ if (BundleCB->State != BUNDLE_UP) {
+ NdisReleaseSpinLock(&BundleCB->Lock);
+ goto PROCESS_FRAME_EXIT;
+ }
+
+ for (i = 1; i < BundleCB->ulNumberOfRoutes; i++) {
+
+ ProtocolCB = BundleCB->ProtocolCBTable[i];
+
+ if (IsValidProtocolCB(ProtocolCB) &&
+ (PPPProtocolID == ProtocolCB->usPPPProtocolID)) {
+ break;
+ }
+ }
+
+ if (!IsValidProtocolCB(ProtocolCB) ||
+ !(ProtocolCB->Flags & PROTOCOL_ROUTED)) {
+ NdisReleaseSpinLock(&BundleCB->Lock);
+ goto PROCESS_FRAME_EXIT;
+ }
+
+ AdapterCB = ProtocolCB->AdapterCB;
+
+ //
+ // We found a valid protocol to indicate this frame to!
+ //
+
+ //
+ // Fill the WanHeader dest address with the transports context
+ //
+ ETH_COPY_NETWORK_ADDRESS(WanHeader, ProtocolCB->TransportAddress);
+
+ if (PPPProtocolID == PPP_PROTOCOL_NBF) {
+
+ //
+ // For nbf fill the length field
+ //
+ WanHeader[12] = (UCHAR)(FrameLength >> 8);
+ WanHeader[13] = (UCHAR)FrameLength;
+
+ if (!(BundleFraming & NBF_PRESERVE_MAC_ADDRESS)) {
+ goto USE_OUR_ADDRESS;
+ }
+
+ //
+ // For nbf and preserve mac address option (SHIVA_FRAMING)
+ // we keep the source address.
+ //
+ ETH_COPY_NETWORK_ADDRESS(&WanHeader[6], FramePointer + 6);
+
+ FramePointer += 12;
+ FrameLength -= 12;
+
+ //
+ // For nbf fill the length field
+ //
+ WanHeader[12] = (UCHAR)(FrameLength >> 8);
+ WanHeader[13] = (UCHAR)FrameLength;
+
+ } else {
+
+ //
+ // For other protocols fill the protocol type
+ //
+ WanHeader[12] = (UCHAR)(ProtocolCB->usProtocolType >> 8);
+ WanHeader[13] = (UCHAR)ProtocolCB->usProtocolType;
+
+ //
+ // Use our address for the src address
+ //
+USE_OUR_ADDRESS:
+ ETH_COPY_NETWORK_ADDRESS(&WanHeader[6], ProtocolCB->NdisWanAddress);
+ }
+
+ ASSERT(WanHeader == RecvDesc->WanHeader);
+ RecvDesc->WanHeaderLength = 14;
+
+ RecvDesc->LookAheadLength = LookAheadLength;
+
+ RecvDesc->CurrentBufferLength = FrameLength;
+ RecvDesc->CurrentBuffer = FramePointer;
+
+ //
+ // Check for non-idle data
+ //
+ if (ProtocolCB->NonIdleDetectFunc != NULL) {
+ PUCHAR HeaderBuffer;
+ ULONG HeaderLength, TotalLength;
+
+ HeaderBuffer = (LookAheadLength != 0) ? LookAhead : FramePointer;
+ HeaderLength = (LookAheadLength != 0) ? LookAheadLength : FrameLength;
+ TotalLength = LookAheadLength + FrameLength;
+
+ if (TRUE == ProtocolCB->NonIdleDetectFunc(HeaderBuffer, HeaderLength, TotalLength)) {
+ NdisWanGetSystemTime(&ProtocolCB->LastRecvNonIdleData);
+ BundleCB->LastRecvNonIdleData = ProtocolCB->LastRecvNonIdleData;
+ }
+ }
+
+ NdisReleaseSpinLock(&BundleCB->Lock);
+
+ if ((AdapterCB->ulReferenceCount == 0) &&
+ NdisWanAcquireMiniportLock(AdapterCB)) {
+
+ NdisAcquireSpinLock(&AdapterCB->Lock);
+
+ if (IsDeferredQueueEmpty(&AdapterCB->DeferredQueue[ReceiveIndication])) {
+ AdapterCB->Flags |= RECEIVE_COMPLETE;
+
+ NdisWanSetDeferred(AdapterCB);
+
+ NdisReleaseSpinLock(&AdapterCB->Lock);
+
+ TotalLength = FrameLength + LookAheadLength;
+
+ if (LookAheadLength == 0) {
+ LookAhead = FramePointer;
+ LookAheadLength = FrameLength;
+ }
+
+ ASSERT((LONG)TotalLength > 0);
+
+ if (NdisWanCB.PromiscuousAdapter != NULL) {
+
+ //
+ // Queue the packet on the promiscous adapter
+ //
+ QueuePromiscuousReceive(RecvDesc);
+ }
+
+ //
+ // We got the lock and there are no pending receive
+ // indications so go ahead and indicate the frame to the protocol
+ //
+ NdisMEthIndicateReceive(AdapterCB->hMiniportHandle,
+ RecvDesc,
+ WanHeader,
+ 14,
+ LookAhead,
+ LookAheadLength,
+ TotalLength);
+
+ NdisWanReleaseMiniportLock(AdapterCB);
+
+ goto PROCESS_FRAME_EXIT;
+ }
+
+ NdisReleaseSpinLock(&AdapterCB->Lock);
+
+ NdisWanReleaseMiniportLock(AdapterCB);
+ }
+
+ QueueDeferredReceive(AdapterCB, RecvDesc);
+
+
+PROCESS_FRAME_EXIT:
+
+ NdisAcquireSpinLock(&BundleCB->Lock);
+
+ NdisWanReturnRecvDesc(BundleCB, RecvDesc);
+
+ NdisReleaseSpinLock(&BundleCB->Lock);
+
+ NdisWanDbgOut(DBG_TRACE, DBG_RECEIVE, ("ProcessFrame: Exit"));
+ return;
+}
+
+VOID
+QueueDeferredReceive(
+ PADAPTERCB AdapterCB,
+ PRECV_DESC RecvDesc
+ )
+{
+ PDEFERRED_DESC DeferredDesc;
+
+ //
+ // The current buffer pointer may point to the decompressor's context
+ // We cannot leave the data in the decompressor so we need to copy it
+ // back to the receive descriptor so we check to see if the current
+ // buffer pointer is already pointing to somewhere in the receive descriptor
+ // If it is we do not need to do the copy.
+ //
+
+ if (RecvDesc->CurrentBuffer < RecvDesc->StartBuffer ||
+ RecvDesc->CurrentBuffer > RecvDesc->StartBuffer + MAX_MRRU) {
+ PUCHAR FramePointer;
+ ULONG FrameLength;
+
+ FramePointer = RecvDesc->CurrentBuffer;
+ FrameLength = RecvDesc->CurrentBufferLength;
+ RecvDesc->CurrentBuffer = RecvDesc->StartBuffer;
+ NdisMoveMemory(RecvDesc->CurrentBuffer,
+ FramePointer,
+ FrameLength);
+ }
+
+ NdisAcquireSpinLock(&AdapterCB->Lock);
+
+ NdisWanGetDeferredDesc(AdapterCB, &DeferredDesc);
+
+ NdisWanInterlockedInc(&RecvDesc->RefCount);
+
+ DeferredDesc->Context = RecvDesc;
+
+ InsertTailDeferredQueue(&AdapterCB->DeferredQueue[ReceiveIndication],
+ DeferredDesc);
+
+ NdisWanSetDeferred(AdapterCB);
+
+ NdisReleaseSpinLock(&AdapterCB->Lock);
+}
+
+BOOLEAN
+DoVJDecompression(
+ PBUNDLECB BundleCB,
+ USHORT ProtocolID,
+ PUCHAR *DataPointer,
+ PULONG DataLength,
+ PUCHAR Header,
+ PULONG HeaderLength
+ )
+{
+ ULONG BundleFraming;
+ PUCHAR FramePointer = *DataPointer;
+ ULONG FrameLength = *DataLength;
+ UCHAR VJCompType = 0;
+ BOOLEAN DoDecomp = FALSE;
+ BOOLEAN VJDetect = FALSE;
+
+ *HeaderLength = 0;
+
+
+ BundleFraming = BundleCB->FramingInfo.RecvFramingBits;
+
+ if (BundleFraming & SLIP_FRAMING) {
+
+ VJCompType = *FramePointer & 0xF0;
+
+ //
+ // If the packet is compressed the header has to be atleast 3 bytes long.
+ // If this is a regular IP packet we do not decompress it.
+ //
+ if ((FrameLength > 2) && (VJCompType != TYPE_IP)) {
+
+ if (VJCompType & 0x80) {
+
+ VJCompType = TYPE_COMPRESSED_TCP;
+
+ } else if (VJCompType == TYPE_UNCOMPRESSED_TCP) {
+
+ *FramePointer &= 0x4F;
+ }
+
+ //
+ // If framing is set for detection, in order for this to be a good
+ // frame for detection we need a type of UNCOMPRESSED_TCP and a
+ // frame that is atleast 40 bytes long.
+ //
+ VJDetect = ((BundleFraming & SLIP_VJ_AUTODETECT) &&
+ (VJCompType == TYPE_UNCOMPRESSED_TCP) &&
+ (FrameLength > 39));
+
+ if ((BundleCB->VJCompress != NULL) &&
+ ((BundleFraming & SLIP_VJ_COMPRESSION) || VJDetect)) {
+
+ //
+ // If VJ compression is set or if we are in
+ // autodetect and this looks like a reasonable
+ // frame
+ //
+ DoDecomp = TRUE;
+
+ }
+ }
+
+ // end of SLIP_FRAMING
+ } else {
+
+ //
+ // Must be PPP framing
+ //
+ if (ProtocolID == PPP_PROTOCOL_COMPRESSED_TCP) {
+ VJCompType = TYPE_COMPRESSED_TCP;
+ } else {
+ VJCompType = TYPE_UNCOMPRESSED_TCP;
+ }
+
+ DoDecomp = TRUE;
+ }
+
+ if (DoDecomp) {
+ ULONG PreCompSize = *DataLength;
+ ULONG PostCompSize;
+
+ if (BundleCB->VJCompress == NULL) {
+ NdisWanDbgOut(DBG_FAILURE, DBG_RECEIVE, ("RecvVJCompress == NULL!"));
+ return(FALSE);
+ }
+
+ NdisWanDbgOut(DBG_INFO, DBG_RECV_VJ,
+ ("rvj %2.2x %d", VJCompType, PreCompSize));
+
+ if ((PostCompSize = sl_uncompress_tcp(DataPointer,
+ DataLength,
+ Header,
+ HeaderLength,
+ VJCompType,
+ BundleCB->VJCompress)) == 0) {
+
+ NdisWanDbgOut(DBG_INFO, DBG_RECV_VJ,
+ ("rvj decomp error!"));
+
+ NdisWanDbgOut(DBG_FAILURE, DBG_RECEIVE, ("Error in sl_uncompress_tcp!"));
+ return(FALSE);
+ }
+
+ if (VJDetect) {
+ NdisAcquireSpinLock(&BundleCB->Lock);
+
+ BundleCB->FramingInfo.RecvFramingBits |= SLIP_VJ_COMPRESSION;
+ BundleCB->FramingInfo.SendFramingBits |= SLIP_VJ_COMPRESSION;
+
+ NdisReleaseSpinLock(&BundleCB->Lock);
+ }
+
+ PostCompSize = *DataLength + *HeaderLength;
+
+ //
+ // Calculate how much expansion we had
+ //
+ BundleCB->BundleStats.BytesReceivedCompressed +=
+ (40 - (PostCompSize - PreCompSize));
+
+ BundleCB->BundleStats.BytesReceivedUncompressed += 40;
+
+ NdisWanDbgOut(DBG_INFO, DBG_RECV_VJ,
+ ("rvj %d", PostCompSize));
+ }
+
+ return(TRUE);
+}
+
+BOOLEAN
+DoDecompDecryptProcessing(
+ PBUNDLECB BundleCB,
+ PLINKCB LinkCB,
+ PUCHAR *DataPointer,
+ PULONG DataLength
+ )
+{
+ USHORT Coherency;
+ PNDISWAN_IO_PACKET IoPacket;
+ ULONG Flags;
+ PWAN_STATS BundleStats;
+ PUCHAR FramePointer = *DataPointer;
+ ULONG FrameLength = *DataLength;
+
+
+ Flags = ((BundleCB->RecvCompInfo.MSCompType & NDISWAN_COMPRESSION) &&
+ (BundleCB->RecvCompressContext != NULL)) ? DO_COMPRESSION : 0;
+
+ if (BundleCB->RecvRC4Key != NULL) {
+ if (BundleCB->RecvCompInfo.MSCompType & NDISWAN_ENCRYPTION) {
+ Flags |= (DO_ENCRYPTION | DO_LEGACY_ENCRYPTION);
+ } else if (BundleCB->RecvCompInfo.MSCompType & NDISWAN_40_ENCRYPTION) {
+ Flags |= (DO_ENCRYPTION | DO_40_ENCRYPTION);
+ }
+#ifdef ENCRYPT_128BIT
+ else if (BundleCB->RecvCompInfo.MSCompType & NDISWAN_128_ENCRYPTION) {
+ Flags |= (DO_ENCRYPTION | DO_128_ENCRYPTION);
+ }
+#endif
+ }
+
+ BundleStats = &BundleCB->BundleStats;
+
+ if (Flags & (DO_COMPRESSION | DO_ENCRYPTION)) {
+ PUCHAR SessionKey = BundleCB->RecvEncryptInfo.SessionKey;
+ ULONG SessionKeyLength = BundleCB->RecvEncryptInfo.SessionKeyLength;
+ PVOID RecvRC4Key = BundleCB->RecvRC4Key;
+ PVOID RecvCompressContext = BundleCB->RecvCompressContext;
+
+ //
+ // Get the coherency counter
+ //
+ Coherency = (*FramePointer << 8) | *(FramePointer + 1);
+ FramePointer += 2;
+ FrameLength -= 2;
+
+
+ if (SEQ_LT(Coherency & 0x0FFF,
+ BundleCB->RCoherencyCounter & 0x0FFF,
+ 0x0800)) {
+ //
+ // We received a sequence number that is less then the
+ // expected sequence number so we must be way out of sync
+ //
+#if DBG
+ DbgPrint("NDISWAN: !!!!rc %4.4x < ec %4.4x!!!!\n", Coherency & 0x0FFF,
+ BundleCB->RCoherencyCounter & 0x0FFF);
+#endif
+ goto RESYNC;
+ }
+
+ //
+ // See if this is a flush packet
+ //
+ if (Coherency & (PACKET_FLUSHED << 8)) {
+
+ NdisWanDbgOut(DBG_INFO, DBG_RECEIVE,
+ ("Recv Packet Flushed 0x%4.4x\n", (Coherency & 0x0FFF)));
+
+ if ((BundleCB->RCoherencyCounter & 0x0FFF) >
+ (Coherency & 0x0FFF)) {
+ BundleCB->RCoherencyCounter += 0x1000;
+ }
+
+ BundleCB->RCoherencyCounter &= 0xF000;
+ BundleCB->RCoherencyCounter |= (Coherency & 0x0FFF);
+
+ if (Flags & DO_ENCRYPTION) {
+
+ //
+ // Re-Init the rc4 receive table
+ //
+ rc4_key(RecvRC4Key,
+ SessionKeyLength,
+ SessionKey);
+
+ }
+
+ if (Flags & DO_COMPRESSION) {
+
+ //
+ // Initialize the decompression history table
+ //
+ initrecvcontext(RecvCompressContext);
+
+ }
+
+ } // end of packet flushed
+
+ if ((Coherency & 0x0FFF) == (BundleCB->RCoherencyCounter & 0x0FFF)) {
+
+ //
+ // We are still in sync
+ //
+
+ BundleCB->RCoherencyCounter++;
+
+ if (Coherency & (PACKET_ENCRYPTED << 8)) {
+
+ //
+ // This packet is encrypted
+ //
+
+ if (!(Flags & DO_ENCRYPTION)) {
+ //
+ // We are not configured to decrypt
+ //
+ return (FALSE);
+ }
+
+ if ((BundleCB->RCoherencyCounter - BundleCB->LastRC4Reset)
+ >= 0x100) {
+
+ //
+ // It is time to change encryption keys
+ //
+
+ //
+ // Always align last reset on 0x100 boundary so as not to
+ // propagate error!
+ //
+ BundleCB->LastRC4Reset = BundleCB->RCoherencyCounter & 0xFF00;
+
+ //
+ // Prevent ushort rollover
+ //
+ if ((BundleCB->LastRC4Reset & 0xF000) == 0xF000) {
+ BundleCB->LastRC4Reset &= 0x0FFF;
+ BundleCB->RCoherencyCounter &= 0x0FFF;
+ }
+
+ if (Flags & DO_LEGACY_ENCRYPTION) {
+
+ //
+ // Change the session key
+ //
+ SessionKey[3] += 1;
+ SessionKey[4] += 3;
+ SessionKey[5] += 13;
+ SessionKey[6] += 57;
+ SessionKey[7] += 19;
+
+ } else {
+
+ //
+ // Change the session key
+ //
+ GetNewKeyFromSHA(&BundleCB->RecvEncryptInfo);
+ }
+
+
+ //
+ // We use rc4 to scramble and recover a new key
+ //
+
+ //
+ // Re-initialize the rc4 receive table to the
+ // intermediate value
+ //
+ rc4_key(RecvRC4Key, SessionKeyLength, SessionKey);
+
+ //
+ // Scramble the existing session key
+ //
+ rc4(RecvRC4Key, SessionKeyLength, SessionKey);
+
+ //
+ // If this is 40 bit encryption we need to fix
+ // the first 3 bytes of the key.
+ //
+
+#ifdef ENCRYPT_128BIT
+ if (!(Flags & DO_128_ENCRYPTION)) {
+#endif
+
+ //
+ // Re-Salt the first 3 bytes
+ //
+ SessionKey[0] = 0xD1;
+ SessionKey[1] = 0x26;
+ SessionKey[2] = 0x9E;
+
+#ifdef ENCRYPT_128BIT
+ }
+#endif
+ NdisWanDbgOut(DBG_TRACE, DBG_CCP,
+ ("RC4 Recv encryption KeyLength %d", BundleCB->RecvEncryptInfo.SessionKeyLength));
+ NdisWanDbgOut(DBG_TRACE, DBG_CCP,
+ ("RC4 Recv encryption Key %.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x",
+ BundleCB->RecvEncryptInfo.SessionKey[0],
+ BundleCB->RecvEncryptInfo.SessionKey[1],
+ BundleCB->RecvEncryptInfo.SessionKey[2],
+ BundleCB->RecvEncryptInfo.SessionKey[3],
+ BundleCB->RecvEncryptInfo.SessionKey[4],
+ BundleCB->RecvEncryptInfo.SessionKey[5],
+ BundleCB->RecvEncryptInfo.SessionKey[6],
+ BundleCB->RecvEncryptInfo.SessionKey[7],
+ BundleCB->RecvEncryptInfo.SessionKey[8],
+ BundleCB->RecvEncryptInfo.SessionKey[9],
+ BundleCB->RecvEncryptInfo.SessionKey[10],
+ BundleCB->RecvEncryptInfo.SessionKey[11],
+ BundleCB->RecvEncryptInfo.SessionKey[12],
+ BundleCB->RecvEncryptInfo.SessionKey[13],
+ BundleCB->RecvEncryptInfo.SessionKey[14],
+ BundleCB->RecvEncryptInfo.SessionKey[15]));
+
+ // Re-initialize the rc4 receive table to the
+ // scrambled session key
+ //
+ rc4_key(RecvRC4Key, SessionKeyLength, SessionKey);
+
+
+ } // end of reset encryption key
+
+ //
+ // Decrypt the data!
+ //
+ rc4(RecvRC4Key,
+ FrameLength,
+ FramePointer);
+
+ } // end of encryption
+
+ if (Coherency & (PACKET_COMPRESSED << 8)) {
+
+ //
+ // This packet is compressed!
+ //
+ if (!(Flags & DO_COMPRESSION)) {
+ //
+ // We are not configured to decompress
+ //
+ return (FALSE);
+ }
+
+ //
+ // Add up bundle stats
+ //
+ BundleStats->BytesReceivedCompressed += FrameLength;
+
+ if (decompress(FramePointer,
+ FrameLength,
+ ((Coherency & (PACKET_AT_FRONT << 8)) >> 8),
+ &FramePointer,
+ &FrameLength,
+ RecvCompressContext) == FALSE) {
+
+#if DBG
+ DbgPrint("dce %4.4x\n", Coherency);
+#endif
+ //
+ // Error decompressing!
+ //
+ BundleCB->RCoherencyCounter--;
+ goto RESYNC;
+
+ }
+
+ BundleStats->BytesReceivedUncompressed += FrameLength;
+
+ } // end of compression
+
+ } else { // end of insync
+RESYNC:
+
+
+ NdisWanDbgOut(DBG_FAILURE, DBG_RECEIVE, ("oos r %4.4x, e %4.4x\n", (Coherency & 0x0FFF),
+ (BundleCB->RCoherencyCounter & 0x0FFF)));
+
+ //
+ // We are out of sync!
+ //
+ NdisWanAllocateMemory(&IoPacket, sizeof(NDISWAN_IO_PACKET) + 100);
+
+ if (IoPacket != NULL) {
+ NDIS_STATUS IoStatus;
+
+ IoPacket->hHandle = LinkCB->hLinkHandle;
+ IoPacket->usHandleType = LINKHANDLE;
+ IoPacket->usHeaderSize = 0;
+ IoPacket->usPacketSize = 6;
+ IoPacket->usPacketFlags = 0;
+ IoPacket->PacketData[0] = 0x80;
+ IoPacket->PacketData[1] = 0xFD;
+ IoPacket->PacketData[2] = 14;
+ IoPacket->PacketData[3] = BundleCB->CCPIdentifier++;
+ IoPacket->PacketData[4] = 0x00;
+ IoPacket->PacketData[5] = 0x04;
+
+ IoStatus = BuildIoPacket(IoPacket, FALSE);
+
+ NdisWanFreeMemory(IoPacket);
+ }
+
+
+ return (FALSE);
+
+ } // end of out of sync
+
+ } else { // end of DoCompEncrypt
+
+ //
+ // For some reason we were not able to
+ // decrypt/decompress!
+ //
+ return (FALSE);
+ }
+
+ *DataPointer = FramePointer;
+ *DataLength = FrameLength;
+
+ return (TRUE);
+}
+
+VOID
+DoCompressionReset(
+ PBUNDLECB BundleCB
+ )
+{
+ if (BundleCB->RecvCompInfo.MSCompType != 0) {
+
+ //
+ // The next outgoing packet will flush
+ //
+ NdisAcquireSpinLock(&BundleCB->Lock);
+ BundleCB->Flags |= RECV_PACKET_FLUSH;
+ NdisReleaseSpinLock(&BundleCB->Lock);
+ }
+}
+
+VOID
+NdisWanReceiveComplete(
+ IN NDIS_HANDLE NdisLinkContext
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ NdisWanDbgOut(DBG_TRACE, DBG_RECEIVE, ("NdisWanReceiveComplete: Enter"));
+
+ NdisWanDbgOut(DBG_TRACE, DBG_RECEIVE, ("NdisWanReceiveComplete: Exit"));
+}
+
+NDIS_STATUS
+NdisWanTransferData(
+ OUT PNDIS_PACKET NdisPacket,
+ OUT PUINT BytesTransferred,
+ IN NDIS_HANDLE MiniportAdapterContext,
+ IN NDIS_HANDLE MiniportReceiveContext,
+ IN UINT ByteOffset,
+ IN UINT BytesToTransfer
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ PRECV_DESC RecvDesc;
+ PUCHAR LookAhead, FramePointer;
+ ULONG LookAheadLength, FrameLength;
+ ULONG BytesToCopy, BytesCopied, PacketOffset = 0;
+
+ NdisWanDbgOut(DBG_TRACE, DBG_RECEIVE, ("NdisWanTransferData: Enter"));
+
+ RecvDesc = (PRECV_DESC)MiniportReceiveContext;
+ LookAhead = RecvDesc->LookAhead;
+ LookAheadLength = RecvDesc->LookAheadLength;
+ FramePointer = RecvDesc->CurrentBuffer;
+ FrameLength = RecvDesc->CurrentBufferLength;
+
+ *BytesTransferred = 0;
+
+ if (BytesToTransfer == 0) {
+ return (NDIS_STATUS_SUCCESS);
+ }
+
+ ASSERT(BytesToTransfer <= (FrameLength + LookAheadLength));
+
+ if ((ByteOffset < LookAheadLength) && (LookAheadLength != 0)) {
+
+ //
+ // First we will copy the lookahead bytes
+ //
+ BytesToCopy = LookAheadLength - ByteOffset;
+
+ BytesToCopy = (BytesToTransfer < BytesToCopy) ?
+ BytesToTransfer : BytesToCopy;
+
+ NdisWanCopyFromBufferToPacket(LookAhead + ByteOffset,
+ BytesToCopy,
+ NdisPacket,
+ PacketOffset,
+ &BytesCopied);
+
+ *BytesTransferred += BytesCopied;
+
+ PacketOffset += BytesCopied;
+ BytesToTransfer -= BytesCopied;
+ ByteOffset = 0;
+ }
+
+ if (FrameLength != 0) {
+
+ //
+ // Now we copy the rest of the frame
+ //
+
+ BytesToCopy = (BytesToTransfer < FrameLength) ?
+ BytesToTransfer : FrameLength;
+
+ NdisWanCopyFromBufferToPacket(FramePointer + ByteOffset,
+ BytesToCopy,
+ NdisPacket,
+ PacketOffset,
+ &BytesCopied);
+
+ *BytesTransferred += BytesCopied;
+ }
+
+ NdisWanDbgOut(DBG_TRACE, DBG_RECEIVE, ("NdisWanTransferData: Exit"));
+
+ return (NDIS_STATUS_SUCCESS);
+}
+
+VOID
+NdisWanCopyFromBufferToPacket(
+ PUCHAR Buffer,
+ ULONG BytesToCopy,
+ PNDIS_PACKET NdisPacket,
+ ULONG PacketOffset,
+ PULONG BytesCopied
+ )
+{
+ PNDIS_BUFFER NdisBuffer;
+ ULONG NdisBufferCount, NdisBufferLength;
+ PVOID VirtualAddress;
+ ULONG LocalBytesCopied = 0;
+
+ *BytesCopied = 0;
+
+ //
+ // Make sure we actually want to do something
+ //
+ if (BytesToCopy == 0) {
+ return;
+ }
+
+ //
+ // Get the buffercount of the packet
+ //
+ NdisQueryPacket(NdisPacket,
+ NULL,
+ &NdisBufferCount,
+ &NdisBuffer,
+ NULL);
+
+ //
+ // Make sure this is not a null packet
+ //
+ if (NdisBufferCount == 0) {
+ return;
+ }
+
+ //
+ // Get first buffer and buffer length
+ //
+ NdisQueryBuffer(NdisBuffer,
+ &VirtualAddress,
+ &NdisBufferLength);
+
+ while (LocalBytesCopied < BytesToCopy) {
+
+ if (NdisBufferLength == 0) {
+
+ NdisGetNextBuffer(NdisBuffer,
+ &NdisBuffer);
+
+ if (NdisBuffer == NULL) {
+ break;
+ }
+
+ NdisQueryBuffer(NdisBuffer,
+ &VirtualAddress,
+ &NdisBufferLength);
+
+ continue;
+ }
+
+ if (PacketOffset != 0) {
+
+ if (PacketOffset > NdisBufferLength) {
+
+ PacketOffset -= NdisBufferLength;
+
+ NdisBufferLength = 0;
+
+ continue;
+
+ } else {
+ VirtualAddress = (PUCHAR)VirtualAddress + PacketOffset;
+ NdisBufferLength -= PacketOffset;
+ PacketOffset = 0;
+ }
+ }
+
+ //
+ // Copy the data
+ //
+ {
+ ULONG AmountToMove;
+ ULONG AmountRemaining;
+
+ AmountRemaining = BytesToCopy - LocalBytesCopied;
+
+ AmountToMove = (NdisBufferLength < AmountRemaining) ?
+ NdisBufferLength : AmountRemaining;
+
+ NdisMoveMemory((PUCHAR)VirtualAddress,
+ Buffer,
+ AmountToMove);
+
+ Buffer += AmountToMove;
+ LocalBytesCopied += AmountToMove;
+ NdisBufferLength -= AmountToMove;
+ }
+ }
+
+ *BytesCopied = LocalBytesCopied;
+}
+
+
+#if 0
+ULONG
+CalculatePPPHeaderLength(
+ PLINKCB LinkCB
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ ULONG PPPHeaderLength = 0;
+ ULONG LinkFraming = LinkCB->LinkInfo.RecvFramingBits;
+
+ if (LinkFraming & PPP_FRAMING) {
+
+ PPPHeaderLength += (LinkFraming & PPP_COMPRESS_ADDRESS_CONTROL) ? 0 : 2;
+
+ if (LinkFraming & PPP_MULTILINK_FRAMING) {
+
+ PPPHeaderLength += (LinkFraming & PPP_COMPRESS_PROTOCOL_FIELD) ? 1 : 2;
+
+ PPPHeaderLength += (LinkFraming & PPP_SHORT_SEQUENCE_HDR_FORMAT) ? 2 : 4;
+ }
+
+ PPPHeaderLength += (LinkFraming & PPP_COMPRESS_PROTOCOL_FIELD) ? 1 : 2;
+
+ }
+
+ return (PPPHeaderLength);
+}
+#endif
+
+VOID
+NdisWanProcessReceiveIndications(
+ PADAPTERCB AdapterCB
+ )
+{
+
+ while (!IsDeferredQueueEmpty(&AdapterCB->DeferredQueue[ReceiveIndication])) {
+ PRECV_DESC RecvDesc;
+ PBUNDLECB BundleCB;
+ PDEFERRED_DESC ReturnDesc;
+
+ ReturnDesc = RemoveHeadDeferredQueue(&AdapterCB->DeferredQueue[ReceiveIndication]);
+ RecvDesc = ReturnDesc->Context;
+ BundleCB = RecvDesc->BundleCB;
+
+ NdisAcquireSpinLock(&BundleCB->Lock);
+
+ if ((BundleCB->State == BUNDLE_UP) &&
+ (BundleCB->Flags & BUNDLE_ROUTED)) {
+ PUCHAR LookAhead;
+ ULONG LookAheadLength;
+ ULONG TotalLength = RecvDesc->LookAheadLength +
+ RecvDesc->CurrentBufferLength;
+
+ NdisReleaseSpinLock(&BundleCB->Lock);
+
+ if (RecvDesc->LookAheadLength == 0) {
+ LookAhead = RecvDesc->CurrentBuffer;
+ LookAheadLength = RecvDesc->CurrentBufferLength;
+ } else {
+ LookAhead = RecvDesc->LookAhead;
+ LookAheadLength = RecvDesc->LookAheadLength;
+ }
+
+ ASSERT((LONG)TotalLength > 0);
+
+ NdisReleaseSpinLock(&AdapterCB->Lock);
+
+ if (NdisWanCB.PromiscuousAdapter != NULL) {
+
+ //
+ // Queue the packet on the promiscous adapter
+ //
+ QueuePromiscuousReceive(RecvDesc);
+ }
+
+ NdisMEthIndicateReceive(AdapterCB->hMiniportHandle,
+ RecvDesc,
+ RecvDesc->WanHeader,
+ 14,
+ LookAhead,
+ LookAheadLength,
+ TotalLength);
+
+ NdisAcquireSpinLock(&AdapterCB->Lock);
+
+ NdisAcquireSpinLock(&BundleCB->Lock);
+ }
+
+ NdisWanReturnRecvDesc(BundleCB, RecvDesc);
+
+ NdisReleaseSpinLock(&BundleCB->Lock);
+
+ InsertHeadDeferredQueue(&AdapterCB->FreeDeferredQueue, ReturnDesc);
+ }
+}
+
+VOID
+QueuePromiscuousReceive(
+ PRECV_DESC RecvDesc
+ )
+{
+ PADAPTERCB AdapterCB = NdisWanCB.PromiscuousAdapter;
+ PLOOPBACK_DESC LoopbackDesc;
+ ULONG AllocationSize, BufferLength;
+ PDEFERRED_DESC DeferredDesc;
+ PUCHAR DataOffset;
+
+ BufferLength = RecvDesc->WanHeaderLength +
+ RecvDesc->LookAheadLength +
+ RecvDesc->CurrentBufferLength;
+
+ AllocationSize = sizeof(LOOPBACK_DESC) + BufferLength;
+
+ NdisWanAllocateMemory(&LoopbackDesc, AllocationSize);
+
+ if (LoopbackDesc == NULL) {
+ return;
+ }
+
+ LoopbackDesc->AllocationSize = (USHORT)AllocationSize;
+ LoopbackDesc->BufferLength = (USHORT)BufferLength;
+
+ LoopbackDesc->Buffer = (PUCHAR)LoopbackDesc + sizeof(LOOPBACK_DESC);
+
+ //
+ // Copy all of the data
+ //
+ DataOffset = LoopbackDesc->Buffer;
+ NdisMoveMemory(DataOffset,
+ RecvDesc->WanHeader,
+ RecvDesc->WanHeaderLength);
+ DataOffset += RecvDesc->WanHeaderLength;
+
+ if (RecvDesc->LookAheadLength != 0) {
+ NdisMoveMemory(DataOffset,
+ RecvDesc->LookAhead,
+ RecvDesc->LookAheadLength);
+ DataOffset += RecvDesc->LookAheadLength;
+ }
+
+ NdisMoveMemory(DataOffset,
+ RecvDesc->CurrentBuffer,
+ RecvDesc->CurrentBufferLength);
+
+ NdisAcquireSpinLock(&AdapterCB->Lock);
+
+ NdisWanGetDeferredDesc(AdapterCB, &DeferredDesc);
+
+ if (DeferredDesc == NULL) {
+
+ NdisWanFreeMemory(LoopbackDesc);
+ return;
+ }
+
+ DeferredDesc->Context = (PVOID)LoopbackDesc;
+
+ InsertTailDeferredQueue(&AdapterCB->DeferredQueue[Loopback], DeferredDesc);
+
+ NdisWanSetDeferred(AdapterCB);
+
+ NdisReleaseSpinLock(&AdapterCB->Lock);
+}
+
+BOOLEAN
+IpIsDataFrame(
+ PUCHAR HeaderBuffer,
+ ULONG HeaderBufferLength,
+ ULONG TotalLength
+ )
+{
+ UINT tcpheaderlength ;
+ UINT ipheaderlength ;
+ UCHAR *tcppacket;
+ UCHAR *ippacket = HeaderBuffer;
+ IPHeader UNALIGNED *ipheader = (IPHeader UNALIGNED *) HeaderBuffer;
+
+
+#define TYPE_UDP 17
+#define UDPPACKET_SRC_PORT_137(x) ((UCHAR) *(x + ((*x & 0x0f)*4) + 1) == 137)
+
+ if (ipheader->ip_p == TYPE_UDP) {
+
+ if (!UDPPACKET_SRC_PORT_137(ippacket))
+
+ return TRUE ;
+
+ else {
+
+ //
+ // UDP port 137 - is wins traffic. we count this as idle traffic.
+ //
+ return FALSE ;
+ }
+
+ }
+
+#define TYPE_TCP 6
+#define TCPPACKET_SRC_OR_DEST_PORT_139(x,y) (((UCHAR) *(x + y + 1) == 139) || ((UCHAR) *(x + y + 3) == 139))
+
+ //
+ // TCP packets with SRC | DEST == 139 which are ACKs (0 data) or Session Alives
+ // are considered as idle
+ //
+ if (ipheader->ip_p == TYPE_TCP) {
+
+ ipheaderlength = ((UCHAR)*ippacket & 0x0f)*4 ;
+ tcppacket = ippacket + ipheaderlength ;
+ tcpheaderlength = (*(tcppacket + 10) >> 4)*4 ;
+
+ if (!TCPPACKET_SRC_OR_DEST_PORT_139(ippacket,ipheaderlength))
+ return TRUE ;
+
+ //
+ // NetBT traffic
+ //
+
+ //
+ // if zero length tcp packet - this is an ACK on 139 - filter this.
+ //
+ if (TotalLength == (ipheaderlength + tcpheaderlength))
+ return FALSE ;
+
+ //
+ // Session alives are also filtered.
+ //
+ if ((UCHAR) *(tcppacket+tcpheaderlength) == 0x85)
+ return FALSE ;
+ }
+
+ //
+ // all other ip traffic is valid traffic
+ //
+ return TRUE ;
+}
+
+BOOLEAN
+IpxIsDataFrame(
+ PUCHAR HeaderBuffer,
+ ULONG HeaderBufferLength,
+ ULONG TotalLength
+ )
+{
+
+/*++
+
+Routine Description:
+
+ This routine is called when a frame is received on a WAN
+ line. It returns TRUE unless:
+
+ - The frame is from the RIP socket
+ - The frame is from the SAP socket
+ - The frame is a netbios keep alive
+ - The frame is an NCP keep alive
+
+Arguments:
+
+ HeaderBuffer - points to a contiguous buffer starting at the IPX header.
+
+ HeaderBufferLength - Length of the header buffer (could be same as totallength)
+
+ TotalLength - the total length of the frame
+
+Return Value:
+
+ TRUE - if this is a connection-based packet.
+
+ FALSE - otherwise.
+
+--*/
+
+ IPX_HEADER UNALIGNED * IpxHeader = (IPX_HEADER UNALIGNED *)HeaderBuffer;
+ USHORT SourceSocket;
+
+ //
+ // First get the source socket.
+ //
+ SourceSocket = IpxHeader->SourceSocket;
+
+ //
+ // Not connection-based
+ //
+ if ((SourceSocket == RIP_SOCKET) ||
+ (SourceSocket == SAP_SOCKET)) {
+
+ return FALSE;
+
+ }
+
+ //
+ // See if there are at least two more bytes to look at.
+ //
+ if (TotalLength >= sizeof(IPX_HEADER) + 2) {
+
+ if (SourceSocket == NB_SOCKET) {
+
+ UCHAR ConnectionControlFlag;
+ UCHAR DataStreamType;
+ USHORT TotalDataLength;
+
+ //
+ // ConnectionControlFlag and DataStreamType will always follow
+ // IpxHeader
+ //
+ ConnectionControlFlag = ((PUCHAR)(IpxHeader+1))[0];
+ DataStreamType = ((PUCHAR)(IpxHeader+1))[1];
+
+ //
+ // If this is a SYS packet with or without a request for ACK and
+ // has session data in it.
+ //
+ if (((ConnectionControlFlag == 0x80) || (ConnectionControlFlag == 0xc0)) &&
+ (DataStreamType == 0x06)) {
+
+ //
+ // TotalDataLength is in the same buffer.
+ //
+ TotalDataLength = ((USHORT UNALIGNED *)(IpxHeader+1))[4];
+
+ //
+ // KeepAlive - return FALSE
+ //
+ if (TotalDataLength == 0) {
+ return FALSE;
+ }
+ }
+
+ } else {
+
+ //
+ // Now see if it is an NCP keep alive. It can be from rip or from
+ // NCP on this machine
+ //
+ if (TotalLength == sizeof(IPX_HEADER) + 2) {
+
+ UCHAR KeepAliveSignature = ((PUCHAR)(IpxHeader+1))[1];
+
+ if ((KeepAliveSignature == '?') ||
+ (KeepAliveSignature == 'Y')) {
+ return FALSE;
+ }
+ }
+ }
+ }
+
+ //
+ // This was a normal packet, so return TRUE
+ //
+
+ return TRUE;
+}
+
+BOOLEAN
+NbfIsDataFrame(
+ PUCHAR HeaderBuffer,
+ ULONG HeaderBufferLength,
+ ULONG TotalLength
+ )
+{
+/*++
+
+Routine Description:
+
+ This routine looks at a data packet from the net to deterimine if there is
+ any data flowing on the connection.
+
+Arguments:
+
+ HeaderBuffer - Pointer to the dlc header for this packet.
+
+ HeaderBufferLength - Length of the header buffer (could be same as totallength)
+
+ TotalLength - the total length of the frame
+
+Return Value:
+
+ True if this is a frame that indicates data traffic on the connection.
+ False otherwise.
+
+--*/
+
+ PDLC_FRAME DlcHeader = (PDLC_FRAME)HeaderBuffer;
+ BOOLEAN Command = (BOOLEAN)!(DlcHeader->Ssap & DLC_SSAP_RESPONSE);
+ PNBF_HDR_CONNECTION nbfHeader;
+
+ if (TotalLength < sizeof(PDLC_FRAME)) {
+ return(FALSE);
+ }
+
+ if (!(DlcHeader->Byte1 & DLC_I_INDICATOR)) {
+
+ //
+ // We have an I frame.
+ //
+
+ if (TotalLength < 4 + sizeof(NBF_HDR_CONNECTION)) {
+
+ //
+ // It's a runt I-frame.
+ //
+
+ return(FALSE);
+ }
+
+ nbfHeader = (PNBF_HDR_CONNECTION) ((PUCHAR)DlcHeader + 4);
+
+ switch (nbfHeader->Command) {
+ case NBF_CMD_DATA_FIRST_MIDDLE:
+ case NBF_CMD_DATA_ONLY_LAST:
+ case NBF_CMD_DATA_ACK:
+ case NBF_CMD_SESSION_CONFIRM:
+ case NBF_CMD_SESSION_INITIALIZE:
+ case NBF_CMD_NO_RECEIVE:
+ case NBF_CMD_RECEIVE_OUTSTANDING:
+ case NBF_CMD_RECEIVE_CONTINUE:
+ return(TRUE);
+ break;
+
+ default:
+ return(FALSE);
+ break;
+ }
+ }
+ return(FALSE);
+
+}
+
+#ifdef NT
+
+VOID
+CompleteIoRecvPacket(
+ PBUNDLECB BundleCB,
+ PLINKCB LinkCB,
+ USHORT PPPProtocolID,
+ PRECV_DESC RecvDesc
+ )
+{
+ PWAN_ASYNC_EVENT AsyncEvent;
+ PUCHAR FramePointer = RecvDesc->CurrentBuffer;
+ ULONG FrameLength = RecvDesc->CurrentBufferLength;
+ KIRQL Irql;
+
+ NdisWanDbgOut(DBG_TRACE, DBG_RECEIVE, ("CompleteIoRecvPacket: Enter"));
+
+ IoAcquireCancelSpinLock(&Irql);
+
+ if (!IsListEmpty(&RecvPacketQueue.List)) {
+ PNDISWAN_IO_PACKET IoPacket;
+ PIRP Irp;
+ PIO_STACK_LOCATION IrpSp;
+ ULONG SizeNeeded, BufferLength;
+
+ AsyncEvent =
+ (PWAN_ASYNC_EVENT)NdisWanInterlockedRemoveHeadList(&RecvPacketQueue.List,
+ &RecvPacketQueue.Lock.SpinLock);
+
+ NdisWanInterlockedDec(&RecvPacketQueue.ulCount);
+
+ Irp = (PIRP)AsyncEvent->Context;
+
+ IrpSp = IoGetCurrentIrpStackLocation(Irp);
+
+ BufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
+
+ SizeNeeded = sizeof(NDISWAN_IO_PACKET) + 14 + FrameLength;
+
+ if ((BufferLength >= SizeNeeded) && (LinkCB->hLinkContext != NULL)) {
+ PUCHAR Data;
+
+ IoPacket = Irp->AssociatedIrp.SystemBuffer;
+
+ IoPacket->hHandle = LinkCB->hLinkContext;
+ IoPacket->usHandleType = LINKHANDLE;
+ IoPacket->usHeaderSize = 14;
+ IoPacket->usPacketSize = (USHORT)FrameLength + 14;
+ IoPacket->usPacketFlags = 0;
+
+ Data = IoPacket->PacketData;
+
+ //
+ // First build the header
+ //
+ Data[0] =
+ Data[6] = ' ';
+
+ Data[1] =
+ Data[7] = 'R';
+
+ Data[2] =
+ Data[8] = 'E';
+
+ Data[3] =
+ Data[9] = 'C';
+
+ Data[4] =
+ Data[10] = 'V';
+
+ Data[5] =
+ Data[11] = (UCHAR)LinkCB->hLinkHandle;
+
+ Data[12] = (UCHAR)(PPPProtocolID >> 8);
+ Data[13] = (UCHAR)PPPProtocolID;
+
+ NdisMoveMemory(RecvDesc->WanHeader, Data, 14);
+ RecvDesc->WanHeaderLength = 14;
+
+ //
+ // Now copy the data
+ //
+ NdisMoveMemory(Data + 14,
+ FramePointer,
+ FrameLength);
+
+ IoSetCancelRoutine(Irp, NULL);
+ Irp->IoStatus.Status = STATUS_SUCCESS;
+ Irp->IoStatus.Information = SizeNeeded;
+
+ IoReleaseCancelSpinLock(Irql);
+
+ IoCompleteRequest(Irp, IO_NETWORK_INCREMENT);
+
+ //
+ // Free the wan_async_event structure
+ //
+ NdisWanFreeMemory(AsyncEvent);
+
+ if (NdisWanCB.PromiscuousAdapter != NULL) {
+ RecvDesc->LookAheadLength = 0;
+
+ //
+ // Queue the packet on the promiscous adapter
+ //
+ QueuePromiscuousReceive(RecvDesc);
+ }
+
+ } else {
+
+#if DBG
+ DbgPrint("NDISWAN: Error I/O recv: bufferlength %d, linkcontext: 0x%8.8x\n",
+ BufferLength, LinkCB->hLinkContext);
+#endif
+ InsertHeadList(&RecvPacketQueue.List, &AsyncEvent->Linkage);
+ NdisWanInterlockedInc(&NdisWanCB.IORecvError2);
+ IoReleaseCancelSpinLock(Irql);
+ }
+
+ } else {
+#if DBG
+ DbgPrint("NDISWAN: No I/O recv packets available!\n");
+#endif
+ NdisWanInterlockedInc(&NdisWanCB.IORecvError1);
+ IoReleaseCancelSpinLock(Irql);
+ }
+
+ NdisWanDbgOut(DBG_TRACE, DBG_RECEIVE, ("CompleteIoRecvPacket: Exit"));
+}
+
+
+#endif // end ifdef NT
diff --git a/private/ntos/ndis/ndiswan/request.c b/private/ntos/ndis/ndiswan/request.c
new file mode 100644
index 000000000..238dbed53
--- /dev/null
+++ b/private/ntos/ndis/ndiswan/request.c
@@ -0,0 +1,541 @@
+/*++
+
+Copyright (c) 1990-1995 Microsoft Corporation
+
+Module Name:
+
+ Request.c
+
+Abstract:
+
+
+Author:
+
+ Tony Bell (TonyBe) June 06, 1995
+
+Environment:
+
+ Kernel Mode
+
+Revision History:
+
+ TonyBe 06/06/95 Created
+
+--*/
+
+#include "wan.h"
+
+
+static UINT SupportedOids[] =
+{
+ OID_GEN_SUPPORTED_LIST,
+ OID_GEN_HARDWARE_STATUS,
+ OID_GEN_MEDIA_SUPPORTED,
+ OID_GEN_MEDIA_IN_USE,
+ OID_GEN_MAXIMUM_LOOKAHEAD,
+ OID_GEN_MAXIMUM_FRAME_SIZE,
+ OID_GEN_LINK_SPEED,
+ OID_GEN_TRANSMIT_BUFFER_SPACE,
+ OID_GEN_RECEIVE_BUFFER_SPACE,
+ OID_GEN_TRANSMIT_BLOCK_SIZE,
+ OID_GEN_RECEIVE_BLOCK_SIZE,
+ OID_GEN_VENDOR_ID,
+ OID_GEN_VENDOR_DESCRIPTION,
+ OID_GEN_CURRENT_PACKET_FILTER,
+ OID_GEN_CURRENT_LOOKAHEAD,
+ OID_GEN_DRIVER_VERSION,
+ OID_GEN_MAXIMUM_TOTAL_SIZE,
+ OID_GEN_MAC_OPTIONS,
+ OID_GEN_XMIT_OK,
+ OID_GEN_RCV_OK,
+ OID_GEN_XMIT_ERROR,
+ OID_GEN_RCV_ERROR,
+ OID_GEN_RCV_NO_BUFFER,
+ OID_802_3_PERMANENT_ADDRESS,
+ OID_802_3_CURRENT_ADDRESS,
+ OID_802_3_MULTICAST_LIST,
+ OID_802_3_MAXIMUM_LIST_SIZE,
+ OID_WAN_PERMANENT_ADDRESS,
+ OID_WAN_CURRENT_ADDRESS,
+ OID_WAN_QUALITY_OF_SERVICE,
+ OID_WAN_MEDIUM_SUBTYPE,
+ OID_WAN_PROTOCOL_TYPE,
+ OID_WAN_HEADER_FORMAT,
+ OID_WAN_LINE_COUNT
+};
+
+
+NDIS_STATUS
+NdisWanOidProc(
+ IN PADAPTERCB pAdapterCB,
+ IN NDIS_OID Oid,
+ IN ULONG SetQueryFlag,
+ IN PVOID InformationBuffer,
+ IN ULONG InformationBufferLength,
+ OUT PULONG BytesWritten,
+ OUT PULONG BytesNeeded
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+ ULONG OidType = Oid & 0xFF000000;
+ NDIS_MEDIUM MediumType;
+ ULONG GenericULong = 0, i;
+ USHORT GenericUShort = 0;
+ UCHAR GenericArray[6];
+ PVOID MoveSource = (PVOID)&GenericULong;
+ ULONG MoveBytes = sizeof(ULONG);
+ NDIS_HARDWARE_STATUS HardwareStatus;
+ ULONG Filter = 0;
+
+ NdisAcquireSpinLock(&pAdapterCB->Lock);
+
+ //
+ // We will break the OID's down into smaller categories
+ //
+ switch (OidType) {
+
+ //
+ // Swith on General Oid's
+ //
+ case OID_GEN:
+ switch (Oid) {
+ case OID_GEN_SUPPORTED_LIST:
+ MoveSource = (PVOID)SupportedOids;
+ MoveBytes = sizeof(SupportedOids);
+ break;
+
+ case OID_GEN_HARDWARE_STATUS:
+ HardwareStatus = pAdapterCB->HardwareStatus;
+ MoveSource = (PVOID)&HardwareStatus;
+ MoveBytes = sizeof(HardwareStatus);
+ break;
+
+ case OID_GEN_MEDIA_SUPPORTED:
+ case OID_GEN_MEDIA_IN_USE:
+ MediumType = pAdapterCB->MediumType;
+ MoveSource = (PVOID)&MediumType;
+ MoveBytes = sizeof(MediumType);
+ break;
+
+ case OID_GEN_MAXIMUM_LOOKAHEAD:
+ case OID_GEN_CURRENT_LOOKAHEAD:
+ case OID_GEN_MAXIMUM_FRAME_SIZE:
+ GenericULong = (ULONG)MAX_FRAME_SIZE;
+ break;
+
+ case OID_GEN_LINK_SPEED:
+ //
+ // Who knows what the initial link speed is?
+ // This should not be called, right?
+ //
+ GenericULong = (ULONG)288;
+ break;
+
+ case OID_GEN_TRANSMIT_BUFFER_SPACE:
+ case OID_GEN_RECEIVE_BUFFER_SPACE:
+ GenericULong = (ULONG)(MAX_FRAME_SIZE * MAX_OUTSTANDING_PACKETS);
+ break;
+
+ case OID_GEN_TRANSMIT_BLOCK_SIZE:
+ case OID_GEN_RECEIVE_BLOCK_SIZE:
+ case OID_GEN_MAXIMUM_TOTAL_SIZE:
+ GenericULong = (ULONG)(MAX_TOTAL_SIZE);
+ break;
+
+ case OID_GEN_VENDOR_ID:
+ GenericULong = 0xFFFFFFFF;
+ MoveBytes = 3;
+ break;
+
+ case OID_GEN_VENDOR_DESCRIPTION:
+ MoveSource = (PVOID)"NdisWan Adapter";
+ MoveBytes = 16;
+ break;
+
+ case OID_GEN_CURRENT_PACKET_FILTER:
+ if (SetQueryFlag == SET_OID) {
+ if (InformationBufferLength > 3) {
+ NdisMoveMemory(&Filter, InformationBuffer, 4);
+
+ if (Filter & NDIS_PACKET_TYPE_PROMISCUOUS) {
+ NdisWanCB.PromiscuousAdapter = pAdapterCB;
+ } else if (NdisWanCB.PromiscuousAdapter == pAdapterCB) {
+ NdisWanCB.PromiscuousAdapter = NULL;
+ }
+
+ } else {
+ Status = NDIS_STATUS_BUFFER_TOO_SHORT;
+ *BytesWritten = 0;
+ *BytesNeeded = 4;
+ }
+ }
+ break;
+
+
+ case OID_GEN_DRIVER_VERSION:
+ GenericUShort = 0x0301;
+ MoveSource = (PVOID)&GenericUShort;
+ MoveBytes = sizeof(USHORT);
+ break;
+
+ case OID_GEN_MAC_OPTIONS:
+ GenericULong = (ULONG)(NDIS_MAC_OPTION_RECEIVE_SERIALIZED |
+ NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |
+// NDIS_MAC_OPTION_NO_LOOPBACK |
+ NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |
+// NDIS_MAC_OPTION_FULL_DUPLEX |
+ NDIS_MAC_OPTION_RESERVED |
+ NDIS_MAC_OPTION_NDISWAN);
+ break;
+
+ case OID_GEN_XMIT_OK:
+ break;
+
+ case OID_GEN_RCV_OK:
+ break;
+
+ case OID_GEN_XMIT_ERROR:
+ break;
+
+ case OID_GEN_RCV_ERROR:
+ break;
+
+ case OID_GEN_RCV_NO_BUFFER:
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ //
+ // Switch on ethernet media specific Oid's
+ //
+ case OID_802_3:
+ switch (Oid) {
+ case OID_802_3_PERMANENT_ADDRESS:
+ case OID_802_3_CURRENT_ADDRESS:
+ ETH_COPY_NETWORK_ADDRESS(GenericArray, pAdapterCB->NetworkAddress);
+ MoveSource = (PVOID)GenericArray;
+ MoveBytes = ETH_LENGTH_OF_ADDRESS;
+ break;
+
+ case OID_802_3_MULTICAST_LIST:
+ MoveBytes = 0;
+ break;
+
+ case OID_802_3_MAXIMUM_LIST_SIZE:
+ GenericULong = 1;
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ //
+ // Switch on WAN specific Oid's
+ //
+ case OID_WAN:
+ switch (Oid) {
+ case OID_WAN_PERMANENT_ADDRESS:
+ case OID_WAN_CURRENT_ADDRESS:
+ ETH_COPY_NETWORK_ADDRESS(GenericArray, pAdapterCB->NetworkAddress);
+ MoveSource = (PVOID)GenericArray;
+ MoveBytes = ETH_LENGTH_OF_ADDRESS;
+ break;
+
+ case OID_WAN_QUALITY_OF_SERVICE:
+ GenericULong = NdisWanReliable;
+ break;
+
+ case OID_WAN_MEDIUM_SUBTYPE:
+ GenericULong = NdisWanMediumHub;
+ break;
+
+ case OID_WAN_PROTOCOL_TYPE:
+ if (InformationBufferLength > 5) {
+
+ pAdapterCB->ProtocolType =
+ (((PUCHAR)InformationBuffer)[4] << 8) |
+ ((PUCHAR)InformationBuffer)[5];
+
+ pAdapterCB->ulNumberofProtocols++;
+
+ } else {
+ Status = NDIS_STATUS_BUFFER_TOO_SHORT;
+ *BytesWritten = 0;
+ *BytesNeeded = 6;
+ }
+ break;
+
+ case OID_WAN_HEADER_FORMAT:
+ GenericULong = NdisWanHeaderEthernet;
+ break;
+
+ case OID_WAN_LINE_COUNT:
+ GenericULong = NdisWanCB.ulNumberOfLinks;
+ break;
+
+ default:
+ break;
+ }
+ break;
+ }
+
+ if (Status == NDIS_STATUS_SUCCESS) {
+
+ if ((MoveBytes > InformationBufferLength) &&
+ (SetQueryFlag == QUERY_OID)) {
+
+ //
+ // Not enough room in the information buffer
+ //
+ *BytesNeeded = MoveBytes;
+
+ Status = NDIS_STATUS_INVALID_LENGTH;
+
+ } else {
+
+ *BytesWritten = MoveBytes;
+
+ NdisMoveMemory(InformationBuffer,
+ MoveSource,
+ MoveBytes);
+ }
+
+ }
+
+ NdisReleaseSpinLock(&pAdapterCB->Lock);
+
+ return (Status);
+}
+
+NDIS_STATUS
+NdisWanSubmitNdisRequest(
+ IN PWAN_ADAPTERCB pWanAdapterCB,
+ IN PNDIS_REQUEST pNdisRequest,
+ IN WanRequestType Type,
+ IN WanRequestOrigin Origin
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ NDIS_STATUS Status;
+ PWAN_REQUEST WanRequest;
+
+ NdisWanAllocateMemory(&WanRequest, sizeof(WAN_REQUEST));
+
+ if (WanRequest == NULL) {
+ return (NDIS_STATUS_RESOURCES);
+ }
+
+ WanRequest->pNdisRequest = pNdisRequest;
+ WanRequest->Type = Type;
+ WanRequest->Origin = Origin;
+
+ NdisWanInitializeNotificationEvent(&WanRequest->NotificationEvent);
+
+ AddRequestToList(pWanAdapterCB, WanRequest);
+
+ NdisRequest(&Status,
+ pWanAdapterCB->hNdisBindingHandle,
+ pNdisRequest);
+
+ //
+ // We will only wait for request that are to complete
+ // synchronously with respect to this function. We will
+ // wait here for completion.
+ //
+ if (Type == SYNC) {
+
+ if (Status == NDIS_STATUS_PENDING) {
+
+ NdisWanWaitForNotificationEvent(&WanRequest->NotificationEvent);
+
+ Status = WanRequest->NotificationStatus;
+
+ NdisWanClearNotificationEvent(&WanRequest->NotificationEvent);
+ }
+
+ RemoveRequestFromList(pWanAdapterCB, WanRequest);
+
+ NdisWanFreeMemory(WanRequest);
+ }
+
+ return (Status);
+}
+
+VOID
+AddRequestToList(
+ IN PWAN_ADAPTERCB pWanAdapterCB,
+ IN PWAN_REQUEST pWanRequest
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ NdisAcquireSpinLock(&pWanAdapterCB->Lock);
+
+ pWanRequest->pNext = NULL;
+
+ //
+ // Is the list empty?
+ //
+ if (pWanAdapterCB->pWanRequest == NULL) {
+
+ ASSERT(pWanAdapterCB->pLastWanRequest == NULL);
+
+ pWanAdapterCB->pWanRequest = pWanRequest;
+ } else {
+ pWanAdapterCB->pLastWanRequest->pNext = pWanRequest;
+ }
+
+ //
+ // update the last request
+ //
+ pWanAdapterCB->pLastWanRequest = pWanRequest;
+
+ NdisReleaseSpinLock(&pWanAdapterCB->Lock);
+}
+
+
+VOID
+RemoveRequestFromList(
+ IN PWAN_ADAPTERCB pWanAdapterCB,
+ IN PWAN_REQUEST pWanRequest
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ PWAN_REQUEST CRequest, PRequest;
+
+ NdisAcquireSpinLock(&pWanAdapterCB->Lock);
+
+ //
+ // Make sure that there is something on the list
+ //
+ ASSERT(pWanAdapterCB->pWanRequest != NULL);
+
+ //
+ // Is this request on the head of the list?
+ //
+ if (pWanRequest == pWanAdapterCB->pWanRequest) {
+ pWanAdapterCB->pWanRequest = pWanRequest->pNext;
+
+ //
+ // If this is also the last request update tail
+ //
+ if (pWanRequest == pWanAdapterCB->pLastWanRequest) {
+ pWanAdapterCB->pLastWanRequest = NULL;
+ }
+
+ } else {
+ CRequest =
+ PRequest = pWanAdapterCB->pWanRequest;
+
+ do {
+
+ if (CRequest == pWanRequest) {
+ //
+ // We found it so remove it from the list
+ //
+ PRequest->pNext = CRequest->pNext;
+ break;
+ }
+
+ PRequest = CRequest;
+
+ CRequest = CRequest->pNext;
+
+ } while (CRequest != NULL);
+
+ //
+ // Did we not find the bugger?
+ //
+ ASSERT (CRequest != NULL);
+
+ //
+ // If this is on the tail of the list remove and update tail
+ //
+ if (CRequest == pWanAdapterCB->pLastWanRequest) {
+ pWanAdapterCB->pLastWanRequest = PRequest;
+ }
+ }
+
+ NdisReleaseSpinLock(&pWanAdapterCB->Lock);
+}
+
+PWAN_REQUEST
+GetWanRequest(
+ IN PWAN_ADAPTERCB pWanAdapterCB,
+ IN PNDIS_REQUEST pNdisRequest
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ PWAN_REQUEST pReturnRequest;
+
+ NdisAcquireSpinLock(&pWanAdapterCB->Lock);
+
+ pReturnRequest = pWanAdapterCB->pWanRequest;
+
+ while (pReturnRequest != NULL) {
+ if (pReturnRequest->pNdisRequest == pNdisRequest) {
+ break;
+ }
+ pReturnRequest = pReturnRequest->pNext;
+ }
+
+ ASSERT (pReturnRequest != NULL);
+
+ NdisReleaseSpinLock(&pWanAdapterCB->Lock);
+
+ return (pReturnRequest);
+}
diff --git a/private/ntos/ndis/ndiswan/send.c b/private/ntos/ndis/ndiswan/send.c
new file mode 100644
index 000000000..1cf740be1
--- /dev/null
+++ b/private/ntos/ndis/ndiswan/send.c
@@ -0,0 +1,3080 @@
+/*++
+
+Copyright (c) 1990-1995 Microsoft Corporation
+
+Module Name:
+
+ Send.c
+
+Abstract:
+
+ This file contains the procedures for doing a send from a protocol, bound
+ to the upper interface of NdisWan, to a Wan Miniport link, bound to the
+ lower interfaceof NdisWan. The upper interface of NdisWan conforms to the
+ NDIS 3.1 Miniport specification. The lower interface of NdisWan conforms
+ to the NDIS 3.1 Extentions for Wan Miniport drivers.
+
+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"
+#include "compress.h"
+#include <rc4.h>
+
+#define EXTRA_COPY 1
+
+//
+// Local function prototypes
+//
+NDIS_STATUS
+FrameAndSend(
+ PBUNDLECB BundleCB,
+ PPROTOCOLCB ProtocolCB,
+ PNDIS_PACKET NdisPacket,
+ BOOLEAN DoMultilink,
+ PULONG BytesSent
+ );
+
+NDIS_STATUS
+SendPacketOnBundle(
+ PBUNDLECB BundleCB
+ );
+
+#ifdef BANDWIDTH_ON_DEMAND
+BOOLEAN
+IsProtocolQuotaFilled(
+ PPROTOCOLCB ProtocolCB
+ );
+
+VOID
+AgeSampleTable(
+ PSAMPLE_TABLE SampleTable
+ );
+
+VOID
+UpdateSampleTable(
+ PSAMPLE_TABLE SampleTable,
+ ULONG BytesSent
+ );
+
+BOOLEAN
+IsSampleTableFull(
+ PSAMPLE_TABLE SampleTable
+ );
+
+VOID
+UpdateBandwidthOnDemand(
+ PBUNDLECB BundleCB,
+ ULONG BytesSent
+ );
+VOID
+CheckUpperThreshold(
+ PBUNDLECB BundleCB
+ );
+
+VOID
+CheckLowerThreshold(
+ PBUNDLECB BundleCB
+ );
+
+#endif // end of BANDWIDTH_ON_DEMAND
+
+ULONG
+GetNumSendingLinks(
+ PBUNDLECB BundleCB
+ );
+
+PLINKCB
+GetNextLinkToXmitOn(
+ PBUNDLECB BundleCB
+ );
+
+VOID
+BuildLinkHeader(
+ PHEADER_FRAMING_INFO FramingInfo,
+ PUCHAR StartBuffer
+ );
+
+//VOID
+//AddPPPProtocolID(
+// PHEADER_FRAMING_INFO FramingInfo,
+// USHORT ProtocolID
+// );
+
+//VOID
+//AddMultilinkInfo(
+// PHEADER_FRAMING_INFO FramingInfo,
+// UCHAR Flags,
+// ULONG SequenceNumber,
+// ULONG SequenceMask
+// );
+
+//VOID
+//AddCompressionInfo(
+// PHEADER_FRAMING_INFO FramingInfo,
+// USHORT CoherencyCounter
+// );
+
+
+PNDIS_WAN_PACKET
+GetWanPacketFromLink(
+ PLINKCB LinkCB
+ );
+
+VOID
+ReturnWanPacketToLink(
+ PLINKCB LinkCB,
+ PNDIS_WAN_PACKET WanPacket
+ );
+
+VOID
+DestroyIoPacket(
+ PNDIS_PACKET NdisPacket
+ );
+
+#if DBG
+VOID
+InsertDbgPacket(
+ PDBG_SEND_CONTEXT DbgContext
+ );
+
+BOOLEAN
+RemoveDbgPacket(
+ PDBG_SEND_CONTEXT DbgContext
+ );
+#endif
+
+//
+// end of local function prototypes
+//
+
+NDIS_STATUS
+NdisWanSend(
+ IN NDIS_HANDLE MiniportAdapterContext,
+ IN PNDIS_PACKET NdisPacket,
+ IN UINT Flags
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+ PADAPTERCB AdapterCB = (PADAPTERCB)MiniportAdapterContext;
+ ULONG BundleIndex = 0, ProtocolIndex = 0, BytesCopied = 0;
+ BOOLEAN SendOnWire;
+ PBUNDLECB BundleCB;
+ PPROTOCOLCB ProtocolCB;
+ PETH_HEADER EthernetHeader;
+ PUCHAR DestAddr, SrcAddr;
+ USHORT ProtocolType = AdapterCB->ProtocolType;
+ PNDIS_BUFFER FirstBuffer;
+
+ NdisWanDbgOut(DBG_TRACE, DBG_SEND, ("NdisWanSend: Enter"));
+ NdisWanDbgOut(DBG_INFO, DBG_SEND, ("s-0x%8.8x, 0x%8.8x, 0x%8.8x", NdisPacket,
+ *((PULONG)&NdisPacket->WrapperReserved[0]), *((PULONG)&NdisPacket->WrapperReserved[4])));
+
+ NdisWanInterlockedInc(&AdapterCB->ulReferenceCount);
+
+ //
+ // Get the ethernet address. This is stolen from the
+ // NDIS wrapper code. This may be a Win95 portability issue.
+ //
+ FirstBuffer = NdisPacket->Private.Head;
+ EthernetHeader = (PETH_HEADER)MDL_ADDRESS(FirstBuffer);
+
+// NdisWanCopyFromPacketToBuffer(NdisPacket,
+// 0,
+// sizeof(ETH_HEADER),
+// (PUCHAR)&EthernetHeader,
+// &BytesCopied);
+
+// if (BytesCopied < ETH_LENGTH_OF_ADDRESS) {
+//
+// goto NdisWanSendExit;
+// }
+
+ DestAddr = EthernetHeader->DestAddr;
+ SrcAddr = EthernetHeader->SrcAddr;
+
+ //
+ // Is this destined for the wire or is it self directed?
+ // If SendOnWire is FALSE this is a self directed packet.
+ //
+ ETH_COMPARE_NETWORK_ADDRESSES_EQ(DestAddr, SrcAddr, &SendOnWire);
+
+ //
+ // Do we need to do loopback? We can check for both multicast
+ // and broadcast with one check because we don't differentiate
+ // between the two.
+ //
+ if (!SendOnWire || (DestAddr[0] & 1)) {
+
+ //
+ // Put on loopback queue
+ //
+ NdisWanQueueLoopbackPacket(AdapterCB, NdisPacket);
+
+ }
+
+ if (!SendOnWire || AdapterCB == NdisWanCB.PromiscuousAdapter) {
+
+ goto NdisWanSendExit;
+ }
+
+ //
+ // We play special tricks with NBF because NBF is
+ // guaranteed to have a one-to-one mapping between
+ // an adapter and a bundle.
+ //
+ if (AdapterCB->ProtocolType == PROTOCOL_NBF) {
+
+ BundleCB = AdapterCB->NbfBundleCB;
+
+ if (BundleCB == NULL) {
+ //
+ // This should just fall through and complete successfully.
+ //
+ NdisWanDbgOut(DBG_INFO, DBG_SEND,
+ ("NdisWanSend: BundleCB is NULL!, BundleHandle: 0x%8.8x", BundleIndex));
+ NdisWanDbgOut(DBG_INFO, DBG_SEND,
+ ("NdisWanSend: AdapterCB: 0x%8.8x, ProtocolType: 0x%4.4x!", AdapterCB, ProtocolType));
+
+ goto NdisWanSendExit;
+ }
+
+ ProtocolIndex = (ULONG)AdapterCB->NbfProtocolHandle;
+
+ } else {
+
+ //
+ // If this a multicast or broadcast our destination
+ // address context has been compromised. We have to
+ // lift the bundle information out of the SRC address.
+ //
+ //
+ if (DestAddr[0] & 1) {
+
+ //
+ // Get the stashed BundleIndex
+ //
+ GetTransportBundleIndex(SrcAddr, BundleIndex);
+
+ BUNDLECB_FROM_BUNDLEH(BundleCB, BundleIndex);
+
+ if (BundleCB == NULL) {
+ //
+ // This should just fall through and complete successfully.
+ //
+ NdisWanDbgOut(DBG_INFO, DBG_SEND,
+ ("NdisWanSend: BundleCB is NULL!, BundleHandle: 0x%8.8x", BundleIndex));
+ NdisWanDbgOut(DBG_INFO, DBG_SEND,
+ ("NdisWanSend: AdapterCB: 0x%8.8x, ProtocolType: 0x%4.4x!", AdapterCB, ProtocolType));
+
+ goto NdisWanSendExit;
+ }
+
+ //
+ // Get the ProtocolIndex from the BundleCB's
+ // list of protocols.
+ //
+ GetProtocolIndexFromProtocolList(&BundleCB->ProtocolCBList,
+ ProtocolType,
+ ProtocolIndex);
+
+ } else {
+
+ //
+ // Get the Bundle Index and BundleCB
+ //
+ GetNdisWanBundleIndex(DestAddr, BundleIndex);
+
+ BUNDLECB_FROM_BUNDLEH(BundleCB, BundleIndex);
+
+ if (BundleCB == NULL) {
+ //
+ // This should just fall through and complete successfully.
+ //
+ NdisWanDbgOut(DBG_INFO, DBG_SEND,
+ ("NdisWanSend: BundleCB is NULL!, BundleHandle: 0x%8.8x", BundleIndex));
+ NdisWanDbgOut(DBG_INFO, DBG_SEND,
+ ("NdisWanSend: AdapterCB: 0x%8.8x, ProtocolType: 0x%4.4x!", AdapterCB, ProtocolType));
+
+ goto NdisWanSendExit;
+ }
+
+ //
+ // Get the Protocol Index
+ //
+ GetNdisWanProtocolIndex(DestAddr, ProtocolIndex);
+ }
+ }
+
+ NdisAcquireSpinLock(&BundleCB->Lock);
+
+ //
+ // Get the ProtocolCB from the BundleCB->ProtocolCBTable
+ //
+ ProtocolCBFromProtocolH(BundleCB, ProtocolIndex, ProtocolCB);
+
+ if ((BundleCB->State != BUNDLE_UP) || !(BundleCB->Flags & BUNDLE_ROUTED) ||
+ !IsValidProtocolCB(ProtocolCB) || !(ProtocolCB->Flags & PROTOCOL_ROUTED) ||
+ ProtocolCB->hProtocolHandle == 0) {
+
+ NdisReleaseSpinLock(&BundleCB->Lock);
+ NdisWanDbgOut(DBG_INFO, DBG_SEND,("NdisWanSend: Problem with route!"));
+
+ NdisWanDbgOut(DBG_INFO, DBG_SEND,
+ ("NdisWanSend: BundleCB: 0x%8.8x State: 0x%8.8x, Flags: 0x%8.8x",
+ BundleCB, BundleCB->State, BundleCB->Flags));
+
+ NdisWanDbgOut(DBG_INFO, DBG_SEND,
+ ("NdisWanSend: ProtocolCB: 0x%8.8x, ProtocolHandle: 0x%8.8x, Flags: 0x%8.8x",
+ ProtocolCB, ProtocolIndex, ProtocolCB->Flags));
+
+ goto NdisWanSendExit;
+ }
+
+ NdisWanInterlockedInc(&NdisWanCB.SendCount);
+
+#if DBG
+ {
+ DBG_SEND_CONTEXT DbgContext;
+ DbgContext.Packet = NdisPacket;
+ DbgContext.PacketType = PACKET_TYPE_NDIS;
+ DbgContext.BundleCB = BundleCB;
+ DbgContext.ProtocolCB = ProtocolCB;
+ DbgContext.LinkCB = NULL;
+ DbgContext.ListHead = &ProtocolCB->AdapterCB->DbgNdisPacketList;
+ DbgContext.ListLock = &ProtocolCB->AdapterCB->Lock;
+
+ InsertDbgPacket(&DbgContext);
+ }
+#endif
+
+ //
+ // Queue the packet on the ProtocolCB NdisPacketQueue
+ //
+ InsertTailNdisPacketQueue(ProtocolCB, NdisPacket);
+
+ //
+ // Try to send a packet on the BundleCB. Called
+ // with bundle lock held but returns with lock
+ // free.
+ //
+ Status = SendPacketOnBundle(BundleCB);
+
+ ASSERT (Status == NDIS_STATUS_PENDING);
+
+NdisWanSendExit:
+
+ NdisWanDbgOut(DBG_TRACE, DBG_SEND, ("NdisWanSend: Exit, Status: 0x%8.8x", Status));
+
+ NdisWanInterlockedDec(&AdapterCB->ulReferenceCount);
+
+ return (Status);
+}
+
+VOID
+NdisWanSendCompleteHandler(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN PNDIS_WAN_PACKET WanPacket,
+ IN NDIS_STATUS Status
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+)
+{
+ PLINKCB LinkCB;
+ PBUNDLECB BundleCB;
+ PPROTOCOLCB ProtocolCB;
+ PWAN_IO_PROTOCOL_RESERVED ProtocolReserved;
+ PNDIS_PACKET NdisPacket;
+ BOOLEAN FreeLink = FALSE;
+ BOOLEAN FreeBundle = FALSE;
+
+ NdisWanDbgOut(DBG_TRACE, DBG_SEND, ("NdisWanSendComplete: Enter"));
+ NdisWanDbgOut(DBG_TRACE, DBG_SEND, ("WanPacket: 0x%8.8x", WanPacket));
+
+ //
+ // Get info from the WanPacket
+ //
+ LinkCB = (PLINKCB)WanPacket->ProtocolReserved1;
+ NdisPacket = (PNDIS_PACKET)WanPacket->ProtocolReserved2;
+ ProtocolCB = (PPROTOCOLCB)WanPacket->ProtocolReserved3;
+
+ NdisWanDbgOut(DBG_INFO, DBG_SEND, ("sc-0x%8.8x, 0x%8.8x, 0x%8.8x", NdisPacket,
+ *((PULONG)&NdisPacket->WrapperReserved[0]), *((PULONG)&NdisPacket->WrapperReserved[4])));
+
+ //
+ // Bundle that this link is on
+ //
+ BundleCB = LinkCB->BundleCB;
+
+#if DBG
+{
+ DBG_SEND_CONTEXT DbgContext;
+
+ DbgContext.Packet = WanPacket;
+ DbgContext.PacketType = PACKET_TYPE_WAN;
+ DbgContext.BundleCB = BundleCB;
+ DbgContext.ProtocolCB = ProtocolCB;
+ DbgContext.LinkCB = LinkCB;
+ DbgContext.ListHead = &LinkCB->WanAdapterCB->DbgWanPacketList;
+ DbgContext.ListLock = &LinkCB->WanAdapterCB->Lock;
+ RemoveDbgPacket(&DbgContext);
+}
+#endif
+
+ NdisAcquireSpinLock(&BundleCB->Lock);
+
+ //
+ // Return the WanPacket to the link
+ //
+ ReturnWanPacketToLink(LinkCB, WanPacket);
+
+ //
+ // Update link stats
+ //
+
+ if ((--LinkCB->OutstandingFrames == 0) &&
+ (LinkCB->State == LINK_GOING_DOWN)) {
+
+ LinkCB->State = LINK_DOWN;
+
+ FreeLink = TRUE;
+
+ RemoveLinkFromBundle(BundleCB, LinkCB);
+
+ if (BundleCB->ulLinkCBCount == 0) {
+ BundleCB->State = BUNDLE_GOING_DOWN;
+ }
+ }
+
+ NdisReleaseSpinLock(&BundleCB->Lock);
+
+ ASSERT((SHORT)PMINIPORT_RESERVED_FROM_NDIS(NdisPacket)->ReferenceCount > 0);
+
+ //
+ // See if the reference count is zero
+ //
+ if (--(PMINIPORT_RESERVED_FROM_NDIS(NdisPacket)->ReferenceCount)) {
+
+ //
+ // The reference count is not yet zero
+ //
+ return;
+ }
+
+ TryToCompleteNdisPacket(ProtocolCB->AdapterCB, NdisPacket);
+
+ NdisAcquireSpinLock(&BundleCB->Lock);
+
+ //
+ // If this bundle is going away but is waiting on all outstanding frames
+ // we need to do cleanup.
+ //
+ if (--BundleCB->OutstandingFrames == 0) {
+
+ //
+ // If this bundle is going away but unroute is waiting on
+ // all outstanding frames we need to signal the waiting thread.
+ //
+ if (BundleCB->Flags & FRAMES_PENDING) {
+
+ NdisWanSetSyncEvent(&BundleCB->OutstandingFramesEvent);
+
+ } else if ((BundleCB->State == BUNDLE_GOING_DOWN) &&
+ !(BundleCB->Flags & BUNDLE_ROUTED)){
+
+ BundleCB->State = BUNDLE_DOWN;
+ FreeBundle = TRUE;
+ }
+ }
+
+ //
+ // Called with bundle lock help but returns with lock released
+ //
+ SendPacketOnBundle(BundleCB);
+
+ if (FreeLink) {
+ //
+ // Remove this link from the connection table
+ //
+ RemoveLinkFromConnectionTable(LinkCB);
+ NdisWanReturnLinkCB(LinkCB);
+ }
+
+ if (FreeBundle) {
+ //
+ // Remove this bundle from the connection table
+ //
+ RemoveBundleFromConnectionTable(BundleCB);
+ NdisWanReturnBundleCB(BundleCB);
+ }
+
+ NdisWanDbgOut(DBG_TRACE, DBG_SEND, ("NdisWanSendComplete: Exit"));
+}
+
+VOID
+TryToCompleteNdisPacket(
+ PADAPTERCB AdapterCB,
+ PNDIS_PACKET NdisPacket
+ )
+{
+ //
+ // If this is a packet that we created we need to free the resources
+ //
+ if (PMINIPORT_RESERVED_FROM_NDIS(NdisPacket)->MagicNumber == NDISWAN_MAGIC_NUMBER) {
+
+ DestroyIoPacket(NdisPacket);
+
+ } else {
+ PDEFERRED_DESC DeferredDesc;
+
+ if ((AdapterCB->ulReferenceCount == 0) &&
+ NdisWanAcquireMiniportLock(AdapterCB)) {
+
+ NdisAcquireSpinLock(&AdapterCB->Lock);
+
+ if (IsDeferredQueueEmpty(&AdapterCB->DeferredQueue[SendComplete])) {
+
+ NdisReleaseSpinLock(&AdapterCB->Lock);
+
+#if DBG
+{
+ DBG_SEND_CONTEXT DbgContext;
+ DbgContext.Packet = NdisPacket;
+ DbgContext.PacketType = PACKET_TYPE_NDIS;
+ DbgContext.BundleCB = NULL;
+ DbgContext.ProtocolCB = NULL;
+ DbgContext.LinkCB = NULL;
+ DbgContext.ListHead = &AdapterCB->DbgNdisPacketList;
+ DbgContext.ListLock = &AdapterCB->Lock;
+ RemoveDbgPacket(&DbgContext);
+}
+#endif
+ //
+ // We got the lock and there are no pending send completes
+ // so go ahead and complete this one!
+ //
+ NdisMSendComplete(AdapterCB->hMiniportHandle,
+ NdisPacket,
+ NDIS_STATUS_SUCCESS);
+
+ //
+ // Increment global count
+ //
+ NdisWanInterlockedInc(&NdisWanCB.SendCompleteCount);
+
+ NdisWanReleaseMiniportLock(AdapterCB);
+
+ return;
+ }
+
+ NdisReleaseSpinLock(&AdapterCB->Lock);
+
+ NdisWanReleaseMiniportLock(AdapterCB);
+ }
+
+ NdisAcquireSpinLock(&AdapterCB->Lock);
+
+ NdisWanGetDeferredDesc(AdapterCB, &DeferredDesc);
+
+ DeferredDesc->Context = NdisPacket;
+
+ InsertTailDeferredQueue(&AdapterCB->DeferredQueue[SendComplete], DeferredDesc);
+
+ NdisWanSetDeferred(AdapterCB);
+
+ NdisReleaseSpinLock(&AdapterCB->Lock);
+ }
+}
+
+VOID
+NdisWanProcessSendCompletes(
+ PADAPTERCB AdapterCB
+ )
+{
+
+ while (!IsDeferredQueueEmpty(&AdapterCB->DeferredQueue[SendComplete])) {
+
+ PNDIS_PACKET NdisPacket;
+ PDEFERRED_DESC ReturnDesc;
+
+ ReturnDesc = RemoveHeadDeferredQueue(&AdapterCB->DeferredQueue[SendComplete]);
+
+ NdisReleaseSpinLock(&AdapterCB->Lock);
+
+ NdisPacket = ReturnDesc->Context;
+
+#if DBG
+{
+ DBG_SEND_CONTEXT DbgContext;
+ DbgContext.Packet = NdisPacket;
+ DbgContext.PacketType = PACKET_TYPE_NDIS;
+ DbgContext.BundleCB = NULL;
+ DbgContext.ProtocolCB = NULL;
+ DbgContext.LinkCB = NULL;
+ DbgContext.ListHead = &AdapterCB->DbgNdisPacketList;
+ DbgContext.ListLock = &AdapterCB->Lock;
+ RemoveDbgPacket(&DbgContext);
+}
+#endif
+ NdisMSendComplete(AdapterCB->hMiniportHandle,
+ NdisPacket,
+ NDIS_STATUS_SUCCESS);
+
+ //
+ // Increment global count
+ //
+ NdisWanInterlockedInc(&NdisWanCB.SendCompleteCount);
+
+ NdisAcquireSpinLock(&AdapterCB->Lock);
+
+ InsertHeadDeferredQueue(&AdapterCB->FreeDeferredQueue, ReturnDesc);
+ }
+}
+
+NDIS_STATUS
+SendPacketOnBundle(
+ PBUNDLECB BundleCB
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+ Called with bundle lock held but returns with lock released!!!
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ NDIS_STATUS Status = NDIS_STATUS_PENDING;
+ ULONG ulProtocolSending, BytesSent;
+ PLIST_ENTRY ProtocolCBList;
+ PPROTOCOLCB IOProtocolCB;
+ PPROTOCOLCB ProtocolCB;
+ BOOLEAN DoMultilink = TRUE;
+ PLINKCB LinkCB;
+#ifdef BANDWIDTH_ON_DEMAND
+ ULONG ulFirstTime;
+#endif
+
+ NdisWanDbgOut(DBG_TRACE, DBG_SEND, ("SendPacketOnBundle: Enter"));
+
+ //
+ // Are we already involved in a send on this bundlecb?
+ //
+ if (BundleCB->Flags & IN_SEND) {
+
+ //
+ // If so flag that we should try back later
+ // and get the hell out.
+ //
+ BundleCB->Flags |= TRY_SEND_AGAIN;
+
+ NdisReleaseSpinLock(&BundleCB->Lock);
+
+ return (NDIS_STATUS_PENDING);
+ }
+
+ BundleCB->Flags |= IN_SEND;
+
+ ProtocolCBList = &BundleCB->ProtocolCBList;
+ IOProtocolCB = (PPROTOCOLCB)ProtocolCBList->Flink;
+
+SendPacketOnBundleTryAgain:
+
+ //
+ // This contains a bit mask with a bit set for each possible send queue.
+ // To start off we will set all of the bits so each send queue will have
+ // a chance to send. If a send queue can send it just sets the bit in
+ // the mask so sends will continue to happen. If the send queue does not
+ // have anything to send the bit for that send queue is turned off. When
+ // all bits are turned off we will fall through the send loop.
+ //
+ ulProtocolSending = BundleCB->SendMask;
+
+#ifdef BANDWIDTH_ON_DEMAND
+ ulFirstTime = (ulProtocolSending & ~IOProtocolCB->SendMaskBit);
+#endif
+
+ if ((PVOID)(ProtocolCB = (PPROTOCOLCB)IOProtocolCB->Linkage.Flink) ==
+ (PVOID)ProtocolCBList) {
+ ProtocolCB = NULL;
+ }
+
+ //
+ // Stay in loop as long as we have protocols sending and endpoints
+ // accepting sends.
+ //
+
+ while (ulProtocolSending && (BundleCB->SendingLinks != 0)) {
+ PNDIS_PACKET NdisPacket;
+ PPROTOCOLCB SendingProtocolCB = NULL;
+ ULONG MagicNumber = 0;
+
+ //
+ // Always check to see if there is an I/O (PPP) packet to
+ // be sent!
+ //
+ if (!IsNdisPacketQueueEmpty(IOProtocolCB)) {
+ PWAN_IO_PROTOCOL_RESERVED pProtocolReserved;
+ PLINKCB LinkCB;
+
+ MagicNumber = NDISWAN_MAGIC_NUMBER;
+
+ NdisPacket = IOProtocolCB->HeadNdisPacketQueue;
+
+ pProtocolReserved = (PWAN_IO_PROTOCOL_RESERVED)NdisPacket->ProtocolReserved;
+
+ //
+ // Is this a directed PPP packet
+ //
+ if (((LinkCB = pProtocolReserved->LinkCB) == NULL) ||
+ (LinkCB->State != LINK_UP)) {
+
+ //
+ // The link has gone down since this send was
+ // queued so destroy the packet
+ //
+ RemoveHeadNdisPacketQueue(IOProtocolCB);
+ DestroyIoPacket(NdisPacket);
+ BundleCB->Flags |= TRY_SEND_AGAIN;
+ break;
+
+ }
+
+ if (!IsLinkSendWindowOpen(LinkCB)) {
+ //
+ // We can not send from the I/O queue because the send
+ // window for this link is closed. We will not send
+ // any data until the link has resources!
+ //
+ break;
+
+ }
+
+ BundleCB->NextLinkToXmit = LinkCB;
+ DoMultilink = FALSE;
+
+ //
+ // We are sending this packet so take it off of the list
+ //
+ RemoveHeadNdisPacketQueue(IOProtocolCB);
+
+ ulProtocolSending |= IOProtocolCB->SendMaskBit;
+
+ SendingProtocolCB = IOProtocolCB;
+
+ //
+ // End of I/O send check
+ //
+ } else {
+
+ ulProtocolSending &= ~IOProtocolCB->SendMaskBit;
+
+ //
+ // If there is not another protocol to check get out
+ //
+ if (ProtocolCB == NULL)
+ break;
+
+ if (!IsNdisPacketQueueEmpty(ProtocolCB)) {
+#ifdef BANDWIDTH_ON_DEMAND
+ BOOLEAN FirstPass;
+
+ FirstPass = (ulFirstTime != 0);
+
+ //
+ // Clear the first time bit. The entire mask will only be
+ // cleared when all of the protocols have had a chance to
+ // send at least once.
+ //
+ ulFirstTime &= ~ProtocolCB->SendMaskBit;
+
+ if (IsSampleTableFull(&ProtocolCB->SampleTable)) {
+
+ //
+ // We don't want this protocol to send again
+ // until its sampletable has an open entry so clear
+ // the protocols send bit.
+ //
+ ulProtocolSending &= ~ProtocolCB->SendMaskBit;
+ goto GetNextProtocolCB;
+ }
+
+ //
+ // We will send a packet from this protocol if it's bandwidth
+ // quota has not been met or if it's quota has been met we
+ // can still send if this is not the first time through the
+ // send loop (all other protocols have had a change to send).
+ //
+ if (IsProtocolQuotaFilled(ProtocolCB) && FirstPass) {
+
+ goto GetNextProtocolCB;
+ }
+#endif // end of BANDWIDTH_ON_DEMAND
+
+ ulProtocolSending |= ProtocolCB->SendMaskBit;
+
+ NdisPacket = RemoveHeadNdisPacketQueue(ProtocolCB);
+
+ SendingProtocolCB = ProtocolCB;
+
+ } else {
+
+ //
+ // Protocol does not have anything to send so mark it
+ // and get the next protocol.
+ //
+ ulProtocolSending &= ~ProtocolCB->SendMaskBit;
+
+#ifdef BANDWIDTH_ON_DEMAND
+ ulFirstTime &= ~ProtocolCB->SendMaskBit;
+#endif
+ goto GetNextProtocolCB;
+
+ }
+ }
+
+ ASSERT(NdisPacket != NULL);
+ ASSERT(SendingProtocolCB != NULL);
+
+ //
+ // We we get here we should have a valid NdisPacket with at least one link
+ // that is accepting sends
+ //
+
+ //
+ // The magic number is only set to a non-zero value if this is a send
+ // through our I/O interface.
+ //
+ PMINIPORT_RESERVED_FROM_NDIS(NdisPacket)->MagicNumber = MagicNumber;
+
+ //
+ // We will get the packet into a contiguous buffer, and do framing,
+ // compression and encryption. This is called with the bundle lock
+ // held and returns with it released.
+ //
+ Status = FrameAndSend(BundleCB,
+ SendingProtocolCB,
+ NdisPacket,
+ DoMultilink,
+ &BytesSent);
+
+#ifdef BANDWIDTH_ON_DEMAND
+ //
+ // Update this protocols sample array with the latest send.
+ //
+ UpdateProtocolQuota(SendingProtocolCB, BytesSent);
+
+ //
+ // Update the bandwidth on demand sample array with the latest send.
+ // If we need to notify someone of a bandwidth event do it.
+ //
+ UpdateBandwidthOnDemand(BundleCB, BytesSent);
+#endif
+
+ NdisAcquireSpinLock(&BundleCB->Lock);
+
+ //
+ // This will force round-robin sends if no protocol
+ // prioritization has been set.
+ //
+#ifdef BANDWIDTH_ON_DEMAND
+
+ if (!(BundleCB->Flags & PROTOCOL_PRIORITY) &&
+ (ProtocolCB != NULL)) {
+
+#else // end of BANDWIDTH_ON_DEMAND
+
+ if (ProtocolCB != NULL) {
+
+#endif // end of !BANDWIDTH_ON_DEMAND
+
+GetNextProtocolCB:
+
+ if ((PVOID)(ProtocolCB = (PPROTOCOLCB)ProtocolCB->Linkage.Flink) ==
+ (PVOID)ProtocolCBList) {
+ ProtocolCB = (PPROTOCOLCB)IOProtocolCB->Linkage.Flink;
+ }
+ }
+
+ } // end of the send while loop
+
+ //
+ // Did someone try to do a send while we were already
+ // sending on this bundle?
+ //
+ if (BundleCB->Flags & TRY_SEND_AGAIN) {
+
+ //
+ // If so clear the flag and try another send.
+ //
+ BundleCB->Flags &= ~TRY_SEND_AGAIN;
+ goto SendPacketOnBundleTryAgain;
+ }
+
+ //
+ // Clear the in send flag.
+ //
+ BundleCB->Flags &= ~IN_SEND;
+
+ NdisReleaseSpinLock(&BundleCB->Lock);
+
+ NdisWanDbgOut(DBG_TRACE, DBG_SEND, ("SendPacketOnBundle: Exit"));
+
+ return (Status);
+}
+
+NDIS_STATUS
+FrameAndSend(
+ PBUNDLECB BundleCB,
+ PPROTOCOLCB ProtocolCB,
+ PNDIS_PACKET NdisPacket,
+ BOOLEAN DoMultilink,
+ PULONG BytesSent
+ )
+/*++
+
+Routine Name:
+
+ FrameAndSend
+
+Routine Description:
+
+ This routine does all of the data manipulation required to take the
+ NdisPacket and make it into the appropriate number of WanPackets. These
+ WanPackets will be queued on a list on their linkcbs. The manipulation
+ that occurs includes getting the data from the ndispacket into a contiguous
+ buffer, protocol header compression, data compression, data encryption,
+ PPP framing, multilink fragmentation and framing.
+
+ Called with bundle lock held but returns with lock released!!!
+
+ A finished frame will look like
+
+ PPPHeader
+ ProtocolHeader
+ Data
+
+Arguments:
+
+ BundleCB - Pointer to the BundleCB that we are sending over
+ ProtocolCB - Pointer to the ProtocolCB that this send is for
+ NdisPacket - Pointer to the NdisPacket that is being sent
+
+Return Values:
+
+ NDIS_STATUS_SUCCESS
+
+--*/
+{
+ NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
+ ULONG BytesCopied, PacketDataOffset;
+ ULONG FragmentsLeft, FragmentsSent, DataLeft;
+ PWAN_STATS BundleStats = &BundleCB->BundleStats;
+ USHORT PPPProtocolID = ProtocolCB->usPPPProtocolID;
+
+ //
+ // Framing information flags
+ //
+ ULONG BundleFraming = BundleCB->FramingInfo.SendFramingBits;
+ ULONG LinkFraming;
+
+ //
+ // This is the next link to be transmitted over
+ //
+ PLINKCB LinkCB;
+
+ //
+ // These are pointers to the active WanPacket and
+ // data buffer.
+ //
+ // WanPacket points to the active WanPacket
+ // StartBuffer points to the begining of the frame
+ // DataBuffer points to where the data begins in the frame
+ // FrameLength is the length of the frame
+ // DataLength is the length of the data
+ //
+ PNDIS_WAN_PACKET WanPacket;
+ PUCHAR StartBuffer, CurrentBuffer, DataBuffer;
+ ULONG DataLength = 0;
+
+ //
+ // These are points to the second WanPacket and
+ // data buffer. These are used to compress into
+ // if compression is on.
+ //
+ // WanPacket2 points to the WanPacket used if compression occurs
+ // PacketNotUsed points to the WanPacket that is to be returned
+ // StartBuffer2 points to the begining of the data buffer in WanPacket2
+ //
+ PNDIS_WAN_PACKET WanPacket2, PacketNotUsed;
+ PUCHAR StartBuffer2, CurrentBuffer2, DataBuffer2;
+
+ //
+ // Flags set to make decisions on whether to compress and/or encrypt the data
+ //
+ ULONG Flags;
+
+ BOOLEAN FirstFragment = TRUE;
+
+ //
+ // Used to gather information about the link header
+ //
+ HEADER_FRAMING_INFO FramingInfo1, FramingInfo2;
+ PHEADER_FRAMING_INFO FramingInfo = &FramingInfo1;
+
+ ULONG ProtocolHeaderLength;
+ UCHAR ProtocolBuffer[40];
+ PUCHAR ProtocolHeader = ProtocolBuffer;
+
+ ULONG EthernetHeaderLength;
+#ifdef EXTRA_COPY
+ PUCHAR EthernetHeader;
+#else
+ UCHAR EthernetHeader[12];
+#endif
+
+ NdisWanDbgOut(DBG_TRACE, DBG_SEND, ("FrameAndSend: Enter"));
+
+ //
+ // Clear out the bytes sent count
+ //
+ *BytesSent = 0;
+
+ //
+ // Get the next link to xmit on.
+ //
+ LinkCB = GetNextLinkToXmitOn(BundleCB);
+
+ ASSERT(LinkCB != NULL);
+
+ ASSERT(IsLinkSendWindowOpen(LinkCB));
+
+ //
+ // Set flags for compression, encryption and multilink
+ //
+ Flags = ((BundleCB->SendCompInfo.MSCompType & NDISWAN_COMPRESSION) &&
+ (BundleCB->SendCompressContext != NULL)) ? DO_COMPRESSION : 0;
+
+ if (BundleCB->SendRC4Key != NULL) {
+ if (BundleCB->SendCompInfo.MSCompType & NDISWAN_ENCRYPTION) {
+ Flags |= (DO_ENCRYPTION | DO_LEGACY_ENCRYPTION);
+ } else if (BundleCB->SendCompInfo.MSCompType & NDISWAN_40_ENCRYPTION) {
+ Flags |= (DO_ENCRYPTION | DO_40_ENCRYPTION);
+ }
+#ifdef ENCRYPT_128BIT
+ else if (BundleCB->SendCompInfo.MSCompType & NDISWAN_128_ENCRYPTION) {
+ Flags |= (DO_ENCRYPTION | DO_128_ENCRYPTION);
+ }
+#endif
+ }
+
+ Flags |= (DoMultilink && (BundleFraming & PPP_FRAMING) &&
+ (BundleFraming & PPP_MULTILINK_FRAMING)) ? DO_MULTILINK : 0;
+
+ if (PPPProtocolID == PPP_PROTOCOL_PRIVATE_IO) {
+ Flags |= IO_PROTOCOLID;
+ Flags &= ~(DO_COMPRESSION | DO_ENCRYPTION);
+ }
+
+ Flags |= FIRST_FRAGMENT;
+
+ //
+ // Did the last receive cause us to flush?
+ //
+ if (BundleCB->Flags & RECV_PACKET_FLUSH) {
+ BundleCB->Flags &= ~RECV_PACKET_FLUSH;
+ Flags |= DO_FLUSH;
+ }
+
+ FramingInfo->FramingBits =
+ LinkFraming = LinkCB->LinkInfo.SendFramingBits;
+ FramingInfo->Flags = Flags;
+
+ //
+ // Bump the outstanding frames on the bundle
+ //
+ BundleCB->OutstandingFrames++;
+
+ //
+ // If we are in promiscuous mode we should indicate this
+ // baby back up.
+ //
+ if (NdisWanCB.PromiscuousAdapter != NULL) {
+ NdisWanQueueLoopbackPacket(NdisWanCB.PromiscuousAdapter, NdisPacket);
+ }
+
+ //
+ // See if we are in pass through mode
+ //
+ if (!(BundleFraming & PASS_THROUGH_MODE) &&
+ !(BundleFraming & RAW_PASS_THROUGH_MODE)) {
+
+ //
+ // Get two wanpackets from the next to send link.
+ //
+ WanPacket = GetWanPacketFromLink(LinkCB);
+ PacketNotUsed =
+ WanPacket2 = GetWanPacketFromLink(LinkCB);
+
+ NdisReleaseSpinLock(&BundleCB->Lock);
+
+ //
+ // This is where we will build the frame. This needs to be
+ // on a 8 byte boundary.
+ //
+ StartBuffer = WanPacket->StartBuffer +
+ LinkCB->LinkInfo.HeaderPadding +
+ sizeof(PVOID);
+
+ (ULONG)StartBuffer &= (ULONG)~(sizeof(PVOID) - 1);
+
+ //
+ // This is where we will build the frame. This needs to be
+ // on a 8 byte boundary.
+ //
+ StartBuffer2 = WanPacket2->StartBuffer +
+ LinkCB->LinkInfo.HeaderPadding +
+ sizeof(PVOID);
+
+ (ULONG)StartBuffer2 &= (ULONG)~(sizeof(PVOID) - 1);
+
+ BuildLinkHeader(FramingInfo, StartBuffer);
+
+ FramingInfo2.FramingBits = FramingInfo->FramingBits;
+ FramingInfo2.Flags = FramingInfo->Flags;
+
+ BuildLinkHeader(&FramingInfo2, StartBuffer2);
+
+ DataBuffer =
+ CurrentBuffer = StartBuffer + FramingInfo->HeaderLength;
+
+ DataBuffer2 =
+ CurrentBuffer2 = StartBuffer2 + FramingInfo->HeaderLength;
+
+ //
+ // If this is a netbios frame and we have to ship the mac header
+ //
+ if ((BundleFraming & NBF_PRESERVE_MAC_ADDRESS) &&
+ (PPPProtocolID == PPP_PROTOCOL_NBF)) {
+
+#ifdef EXTRA_COPY
+
+ EthernetHeader = CurrentBuffer;
+
+#endif
+
+ //
+ // Copy Ethernet header to temp buffer
+ //
+ NdisWanCopyFromPacketToBuffer(NdisPacket,
+ 0,
+ 12,
+ EthernetHeader,
+ &BytesCopied);
+ ASSERT(BytesCopied == 12);
+
+ CurrentBuffer += BytesCopied;
+ DataLength += BytesCopied;
+
+ EthernetHeaderLength = BytesCopied;
+ }
+
+ //
+ // We are beyond the mac header (also skip the length/protocoltype field)
+ //
+ if (PPPProtocolID == PPP_PROTOCOL_PRIVATE_IO) {
+ PacketDataOffset = 12;
+ } else {
+ PacketDataOffset = 14;
+ }
+
+ //
+ // Do protocol header compression - IP only!
+ //
+ if ((PPPProtocolID == PPP_PROTOCOL_IP) &&
+ (BundleCB->VJCompress != NULL) &&
+ ((BundleFraming & SLIP_VJ_COMPRESSION) || (BundleFraming & PPP_FRAMING))) {
+ UCHAR CompType = TYPE_IP;
+
+ BundleStats->BytesTransmittedUncompressed += 40;
+
+ //
+ // Get the protocol header
+ //
+ NdisWanCopyFromPacketToBuffer(NdisPacket,
+ PacketDataOffset,
+ 40,
+ ProtocolHeader,
+ &ProtocolHeaderLength);
+
+
+ PacketDataOffset += ProtocolHeaderLength;
+
+ NdisWanDbgOut(DBG_INFO, DBG_SEND_VJ,
+ ("svj %d", ProtocolHeaderLength));
+
+ //
+ // Are we compressing TCP/IP headers? There is a nasty
+ // hack in VJs implementation for attempting to detect
+ // interactive TCP/IP sessions. That is, telnet, login,
+ // klogin, eklogin, and ftp sessions. If detected,
+ // the traffic gets put on a higher TypeOfService (TOS). We do
+ // no such hack for RAS. Also, connection ID compression
+ // is negotiated, but we always don't compress it.
+ //
+ CompType = sl_compress_tcp(&ProtocolHeader,
+ &ProtocolHeaderLength,
+ BundleCB->VJCompress,
+ 0);
+
+
+ if (BundleFraming & SLIP_VJ_COMPRESSION) {
+
+ //
+ // For SLIP, the upper bits of the first byte
+ // are for VJ header compression control bits
+ //
+ ProtocolHeader[0] |= CompType;
+ }
+
+
+#ifdef EXTRA_COPY
+
+ NdisMoveMemory(CurrentBuffer, ProtocolHeader, ProtocolHeaderLength);
+
+ CurrentBuffer += ProtocolHeaderLength;
+ DataLength += ProtocolHeaderLength;
+#else
+
+#endif
+ NdisWanDbgOut(DBG_INFO, DBG_SEND_VJ,
+ ("svj %2.2x %d",CompType, ProtocolHeaderLength));
+
+ BundleStats->BytesTransmittedCompressed += ProtocolHeaderLength;
+
+
+ switch (CompType) {
+ case TYPE_IP:
+ PPPProtocolID = PPP_PROTOCOL_IP;
+ break;
+
+ case TYPE_UNCOMPRESSED_TCP:
+ PPPProtocolID = PPP_PROTOCOL_UNCOMPRESSED_TCP;
+ break;
+
+ case TYPE_COMPRESSED_TCP:
+ PPPProtocolID = PPP_PROTOCOL_COMPRESSED_TCP;
+ break;
+
+ default:
+ DbgBreakPoint();
+ break;
+ }
+
+ }
+
+#ifdef EXTRA_COPY
+ //
+ // Copy the rest of the data from the ndis packet to
+ // a contiguous buffer
+ //
+ NdisWanCopyFromPacketToBuffer(NdisPacket,
+ PacketDataOffset,
+ 0xFFFFFFFF,
+ CurrentBuffer,
+ &BytesCopied);
+
+ DataLength += BytesCopied;
+#endif
+
+ //
+ // Add the PPP Protocol ID to the PPP header
+ //
+ AddPPPProtocolID(FramingInfo, PPPProtocolID);
+
+ //
+ // At this point we have our framinginfo structure created
+ // StartBuffer points to the begining of the frame, DataBuffer
+ // points to the place where the data starts in the frame,
+ // DataLength is the length of the data in the frame.
+ //
+
+ //
+ // If compression and/or encryption is on and this is not a PPP CP frame do
+ // data compression.
+ //
+ if (Flags & (DO_COMPRESSION | DO_ENCRYPTION)) {
+ union {
+ USHORT uShort;
+ UCHAR uChar[2];
+ }CoherencyCounter;
+
+ //
+ // If we are compressing/encrypting, the ProtocolID
+ // is part of the compressed data so fix the pointer
+ // and the length;
+ //
+ DataBuffer -= FramingInfo->ProtocolID.Length;
+ DataBuffer2 -= FramingInfo->ProtocolID.Length;
+
+ DataLength += FramingInfo->ProtocolID.Length;
+ FramingInfo->HeaderLength -= FramingInfo->ProtocolID.Length;
+
+ //
+ // Get the coherency counter
+ //
+ CoherencyCounter.uShort = BundleCB->SCoherencyCounter;
+ CoherencyCounter.uChar[1] &= 0x0F;
+
+ //
+ // Bump the coherency count
+ //
+ BundleCB->SCoherencyCounter++;
+
+ if (Flags & DO_COMPRESSION) {
+
+ BundleStats->BytesTransmittedUncompressed += DataLength;
+
+ if (Flags & DO_FLUSH) {
+ //
+ // Init the compression history table and tree
+ //
+ initsendcontext(BundleCB->SendCompressContext);
+ }
+
+#ifdef EXTRA_COPY
+
+ //
+ // We are doing the copy to get things into a contiguous buffer before
+ // compression occurs
+ //
+ CoherencyCounter.uChar[1] |= compress(DataBuffer,
+ DataBuffer2,
+ &DataLength,
+ BundleCB->SendCompressContext);
+
+#else
+
+ //
+ // Compression will occur on fragments. We are not doing a copy
+ // to get things into a contiguous buffer before compressing
+ //
+
+ //
+ // If we need to include the ethernet header, compress it
+ //
+
+ //
+ // If we have a compressed protocol header, compress it again
+ //
+
+ //
+ // Now we need to walk the NdisBuffer chain compressing each
+ // buffer as we go. We need to get to the buffer where our
+ // current DataOffset is. Once we get to this buffer we will
+ // compress what is left of the buffer. We then go into a loop
+ // that walks the rest of the buffers in the buffer chain.
+ //
+#endif
+
+ if (CoherencyCounter.uChar[1] & PACKET_FLUSHED) {
+
+ //
+ // If encryption is enabled this will force a
+ // reinit of the table
+ //
+ Flags |= DO_FLUSH;
+
+ } else {
+ //
+ // We compressed the packet so now the active WanPacket will be
+ // WanPacket2. We need to copy the PPP header from WanPacket to
+ // WanPacket2. The header includes everything except for the
+ // protocolid field.
+ //
+
+ NdisMoveMemory(StartBuffer2,
+ StartBuffer,
+ FramingInfo->HeaderLength - FramingInfo->ProtocolID.Length);
+
+ //
+ // Now WanPacket2 and all of it's relevant pointers
+ // and structures are active.
+ //
+ PacketNotUsed = WanPacket;
+ WanPacket = WanPacket2;
+ DataBuffer = DataBuffer2;
+ StartBuffer = StartBuffer2;
+ FramingInfo = &FramingInfo2;
+ FramingInfo->HeaderLength -= FramingInfo->ProtocolID.Length;
+ }
+
+ BundleStats->BytesTransmittedCompressed += DataLength;
+ }
+
+ //
+ // Do data encryption
+ //
+ if (Flags & DO_ENCRYPTION) {
+ PUCHAR SessionKey = BundleCB->SendEncryptInfo.SessionKey;
+ ULONG SessionKeyLength = BundleCB->SendEncryptInfo.SessionKeyLength;
+ PVOID SendRC4Key = BundleCB->SendRC4Key;
+
+ //
+ // We may need to reinit the rc4 table
+ //
+ if (Flags & DO_FLUSH) {
+ rc4_key(SendRC4Key, SessionKeyLength, SessionKey);
+ }
+
+ //
+ // Mark this as being encrypted
+ //
+ CoherencyCounter.uChar[1] |= PACKET_ENCRYPTED;
+
+ //
+ // Every 256 frames change the RC4 session key
+ //
+ if ((BundleCB->SCoherencyCounter & 0xFF) == 0) {
+
+ if (Flags & DO_LEGACY_ENCRYPTION) {
+ //
+ // Simple munge for legacy encryption
+ //
+ SessionKey[3] += 1;
+ SessionKey[4] += 3;
+ SessionKey[5] += 13;
+ SessionKey[6] += 57;
+ SessionKey[7] += 19;
+
+ } else {
+
+ //
+ // Use SHA to get new sessionkey
+ //
+ GetNewKeyFromSHA(&BundleCB->SendEncryptInfo);
+
+ }
+
+ //
+ // We use rc4 to scramble and recover a new key
+ //
+
+ //
+ // Re-initialize the rc4 receive table to the
+ // intermediate value
+ //
+ rc4_key(SendRC4Key, SessionKeyLength, SessionKey);
+
+ //
+ // Scramble the existing session key
+ //
+ rc4(SendRC4Key, SessionKeyLength, SessionKey);
+
+ //
+ // If this is 40 bit encryption we need to fix
+ // the first 3 bytes of the key.
+ //
+#ifdef ENCRYPT_128BIT
+ if (!(Flags & DO_128_ENCRYPTION)) {
+
+#endif
+ //
+ // Re-Salt the first 3 bytes
+ //
+ SessionKey[0] = 0xD1;
+ SessionKey[1] = 0x26;
+ SessionKey[2] = 0x9E;
+
+#ifdef ENCRYPT_128BIT
+ }
+
+#endif
+ NdisWanDbgOut(DBG_TRACE, DBG_CCP,
+ ("RC4 Send encryption KeyLength %d", BundleCB->SendEncryptInfo.SessionKeyLength));
+ NdisWanDbgOut(DBG_TRACE, DBG_CCP,
+ ("RC4 Send encryption Key %.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x%.2x",
+ BundleCB->SendEncryptInfo.SessionKey[0],
+ BundleCB->SendEncryptInfo.SessionKey[1],
+ BundleCB->SendEncryptInfo.SessionKey[2],
+ BundleCB->SendEncryptInfo.SessionKey[3],
+ BundleCB->SendEncryptInfo.SessionKey[4],
+ BundleCB->SendEncryptInfo.SessionKey[5],
+ BundleCB->SendEncryptInfo.SessionKey[6],
+ BundleCB->SendEncryptInfo.SessionKey[7],
+ BundleCB->SendEncryptInfo.SessionKey[8],
+ BundleCB->SendEncryptInfo.SessionKey[9],
+ BundleCB->SendEncryptInfo.SessionKey[10],
+ BundleCB->SendEncryptInfo.SessionKey[11],
+ BundleCB->SendEncryptInfo.SessionKey[12],
+ BundleCB->SendEncryptInfo.SessionKey[13],
+ BundleCB->SendEncryptInfo.SessionKey[14],
+ BundleCB->SendEncryptInfo.SessionKey[15]));
+
+ //
+ // Re-initialize the rc4 receive table to the
+ // scrambled session key
+ //
+ rc4_key(SendRC4Key, SessionKeyLength, SessionKey);
+
+ }
+
+ //
+ // Encrypt the data
+ //
+ rc4(SendRC4Key, DataLength, DataBuffer);
+
+ }
+
+
+ //
+ // Did the last receive cause us to flush?
+ //
+ if (Flags & DO_FLUSH) {
+ CoherencyCounter.uChar[1] |= PACKET_FLUSHED;
+ }
+
+ //
+ // Add the coherency bytes to the frame
+ //
+ AddCompressionInfo(FramingInfo, CoherencyCounter.uShort);
+
+ ASSERT(((CoherencyCounter.uShort + 1) & 0x0FFF) ==
+ (BundleCB->SCoherencyCounter & 0x0FFF));
+ }
+
+ NdisAcquireSpinLock(&BundleCB->Lock);
+
+ //
+ // Return the unused wanpacket to the pool
+ //
+ ReturnWanPacketToLink(LinkCB, PacketNotUsed);
+
+ //
+ // At this point we have our framinginfo structure initialized,
+ // StartBuffer pointing to the begining of the frame, DataBuffer
+ // pointing to the begining of the data, DataLength is the
+ // length of the data.
+ //
+ FragmentsLeft = BundleCB->SendingLinks;
+ DataLeft = DataLength;
+ FragmentsSent = 0;
+ FirstFragment = TRUE;
+
+ //
+ // For all fragments we loop fixing up the multilink header
+ // if multilink is on, fixing up pointers in the wanpacket,
+ // and queuing the wanpackets for further processing.
+ //
+ while (DataLeft) {
+ ULONG FragDataLength;
+ ULONG LinkBandwidth;
+
+ if (!FirstFragment) {
+
+ //
+ // We had more than one fragment, get the next
+ // link to send over and a wanpacket from the
+ // link.
+ //
+
+ LinkCB = GetNextLinkToXmitOn(BundleCB);
+
+ ASSERT(IsLinkSendWindowOpen(LinkCB));
+
+ WanPacket = GetWanPacketFromLink(LinkCB);
+
+ //
+ // This is where we will build the frame. This needs to be
+ // on a 8 byte boundary.
+ //
+ StartBuffer = WanPacket->StartBuffer +
+ LinkCB->LinkInfo.HeaderPadding +
+ sizeof(PVOID);
+
+ (ULONG)StartBuffer &= (ULONG)~(sizeof(PVOID) - 1);
+
+ //
+ // Get new framing information and build a new
+ // header for the new link.
+ //
+ FramingInfo->FramingBits =
+ LinkFraming = LinkCB->LinkInfo.SendFramingBits;
+
+ FramingInfo->Flags = (DoMultilink) ? DO_MULTILINK : 0;
+
+ BuildLinkHeader(FramingInfo, StartBuffer);
+ }
+
+ LinkBandwidth = LinkCB->ulBandwidth;
+
+ if ((Flags & DO_MULTILINK) && (FragmentsLeft > 1) &&
+ (LinkBandwidth < 85)) {
+
+ //
+ // Calculate the length of this fragment
+ //
+ FragDataLength = (DataLength * LinkBandwidth / 100);
+
+ FragDataLength = (FragDataLength < NdisWanCB.ulMinFragmentSize) ?
+ NdisWanCB.ulMinFragmentSize : FragDataLength;
+
+ if ((FragDataLength > DataLeft) ||
+ ((LONG)DataLeft - FragDataLength < NdisWanCB.ulMinFragmentSize)) {
+ //
+ // This will leave a fragment of less than min frag size
+ // so send all of the data
+ //
+ FragDataLength = DataLeft;
+ FragmentsLeft = 1;
+ }
+
+
+ } else {
+ //
+ // We either have one fragment left or this link has
+ // more than 85 percent of the bundle so send what
+ // data is left
+ //
+ FragDataLength = DataLeft;
+ FragmentsLeft = 1;
+ }
+
+ if (!FirstFragment) {
+ //
+ // Copy the data to the new buffer from the old buffer.
+ //
+ NdisMoveMemory(StartBuffer + FramingInfo->HeaderLength,
+ DataBuffer,
+ FragDataLength);
+
+ }
+
+ //
+ // Update the data pointer and the length left to send
+ //
+ DataBuffer += FragDataLength;
+ DataLeft -= FragDataLength;
+
+ if (Flags & DO_MULTILINK) {
+ UCHAR MultilinkFlags = 0;
+
+
+ //
+ // Multlink is on so create flags for this
+ // fragment.
+ //
+ if (FirstFragment) {
+ MultilinkFlags = MULTILINK_BEGIN_FRAME;
+ FirstFragment = FALSE;
+ }
+
+ if (FragmentsLeft == 1) {
+ MultilinkFlags |= MULTILINK_END_FRAME;
+ }
+
+ //
+ // Add the multilink header information and
+ // take care of the sequence number.
+ //
+ AddMultilinkInfo(FramingInfo,
+ MultilinkFlags,
+ BundleCB->SendSeqNumber,
+ BundleCB->SendSeqMask);
+
+ NdisWanDbgOut(DBG_INFO, DBG_MULTILINK_SEND, ("sf %8.8x %8.8x %d",
+ BundleCB->SendSeqNumber, MultilinkFlags, FragDataLength));
+
+ BundleCB->SendSeqNumber++;
+
+ }
+
+ //
+ // Initialize the WanPacket
+ //
+ WanPacket->CurrentBuffer = StartBuffer;
+ WanPacket->CurrentLength = FragDataLength + FramingInfo->HeaderLength;
+
+ WanPacket->ProtocolReserved1 = (PVOID)LinkCB;
+ WanPacket->ProtocolReserved2 = (PVOID)NdisPacket;
+ WanPacket->ProtocolReserved3 = (PVOID)ProtocolCB;
+
+ NdisWanDbgOut(DBG_INFO, DBG_MULTILINK_SEND,
+ ("l %8.8x %8.8x", LinkCB->hLinkHandle));
+ //
+ // Add up the bytes that we are sending over all
+ // links in this bundle.
+ //
+ *BytesSent += WanPacket->CurrentLength;
+
+ //
+ // Queue for further processing.
+ //
+ InsertTailList(&BundleCB->SendPacketQueue, &WanPacket->WanPacketQueue);
+
+ FragmentsSent++;
+ FragmentsLeft--;
+
+ } // end of the fragment loop
+
+ ASSERT(FragmentsLeft == 0);
+
+ //
+ // Get the mac reserved structure from the ndispacket. This
+ // is where we will keep the reference count on the packet.
+ //
+ ASSERT((LONG)FragmentsSent > 0 && FragmentsSent <= BundleCB->ulLinkCBCount);
+ PMINIPORT_RESERVED_FROM_NDIS(NdisPacket)->ReferenceCount = (USHORT)FragmentsSent;
+
+ BundleCB->BundleStats.FramesTransmitted++;
+
+ //
+ // At this point we have a list of wanpackets that need to be sent,
+ // update the total bytes associated with this send, and send
+ // the packets over their links.
+ //
+ while (!IsListEmpty(&BundleCB->SendPacketQueue)) {
+ Status = NDIS_STATUS_SUCCESS;
+
+ //
+ // Get the wanpacket off of the list
+ //
+ WanPacket = (PNDIS_WAN_PACKET)RemoveHeadList(&BundleCB->SendPacketQueue);
+
+ //
+ // Get the link to send over
+ //
+ LinkCB = WanPacket->ProtocolReserved1;
+
+ //
+ // Update the outstanding frames on the link
+ //
+ LinkCB->LinkStats.FramesTransmitted++;
+ LinkCB->LinkStats.BytesTransmitted += WanPacket->CurrentLength;
+ BundleCB->BundleStats.BytesTransmitted += WanPacket->CurrentLength;
+
+#if DBG
+ {
+ DBG_SEND_CONTEXT DbgContext;
+ DbgContext.Packet = WanPacket;
+ DbgContext.PacketType = PACKET_TYPE_WAN;
+ DbgContext.BundleCB = BundleCB;
+ DbgContext.ProtocolCB = ProtocolCB;
+ DbgContext.LinkCB = LinkCB;
+ DbgContext.ListHead = &LinkCB->WanAdapterCB->DbgWanPacketList;
+ DbgContext.ListLock = &LinkCB->WanAdapterCB->Lock;
+
+ InsertDbgPacket(&DbgContext);
+ }
+#endif
+ NdisReleaseSpinLock(&BundleCB->Lock);
+
+ //
+ // If the link is up send the packet
+ //
+ if (LinkCB->State == LINK_UP) {
+
+
+ NdisWanDbgOut(DBG_TRACE, DBG_SEND, ("FrameAndSend: LinkCB: 0x%8.8x, WanPacket: 0x%8.8x", LinkCB, WanPacket));
+
+ WanMiniportSend(&Status,
+ LinkCB->WanAdapterCB->hNdisBindingHandle,
+ LinkCB->LineUpInfo.NdisLinkHandle,
+ WanPacket);
+
+ NdisWanDbgOut(DBG_TRACE, DBG_SEND, ("FrameAndSend: Status: 0x%8.8x", Status));
+ }
+
+ //
+ // If we get something other than pending back we need to
+ // do the send complete.
+ //
+ if (Status != NDIS_STATUS_PENDING) {
+
+ NdisWanSendCompleteHandler(NULL,
+ WanPacket,
+ NDIS_STATUS_SUCCESS);
+
+ Status = NDIS_STATUS_PENDING;
+ }
+
+ NdisAcquireSpinLock(&BundleCB->Lock);
+ }
+
+ NdisReleaseSpinLock(&BundleCB->Lock);
+
+ } else {
+ //
+ // We need to get a WanPacket
+ //
+ WanPacket = GetWanPacketFromLink(LinkCB);
+
+ NdisReleaseSpinLock(&BundleCB->Lock);
+
+ //
+ // Copy the data into the WanPacket
+ //
+ //
+ // This is where we will build the frame. This needs to be
+ // on a 8 byte boundary.
+ //
+ StartBuffer = WanPacket->StartBuffer +
+ LinkCB->LinkInfo.HeaderPadding +
+ sizeof(PVOID);
+
+ (ULONG)StartBuffer &= (ULONG)~(sizeof(PVOID) - 1);
+
+ NdisWanCopyFromPacketToBuffer(NdisPacket,
+ 0,
+ 0xFFFFFFFF,
+ StartBuffer,
+ &BytesCopied);
+
+ //
+ // If we are in pass through mode set the protocol type
+ //
+ if (BundleFraming & PASS_THROUGH_MODE) {
+ StartBuffer[12] = (UCHAR)(ProtocolCB->usProtocolType << 8);
+ StartBuffer[13] = (UCHAR)ProtocolCB->usProtocolType;
+ }
+
+ WanPacket->CurrentBuffer = StartBuffer;
+ WanPacket->CurrentLength = BytesCopied;
+ WanPacket->ProtocolReserved1 = (PVOID)LinkCB;
+ WanPacket->ProtocolReserved2 = (PVOID)NdisPacket;
+ WanPacket->ProtocolReserved3 = (PVOID)ProtocolCB;
+
+ if (LinkCB->State == LINK_UP) {
+
+ NdisWanDbgOut(DBG_TRACE, DBG_SEND, ("FrameAndSend: LinkCB: 0x%8.8x, WanPacket: 0x%8.8x", LinkCB, WanPacket));
+
+ WanMiniportSend(&Status,
+ LinkCB->WanAdapterCB->hNdisBindingHandle,
+ LinkCB->LineUpInfo.NdisLinkHandle,
+ WanPacket);
+ }
+
+ //
+ // If we get something other than pending back we need to
+ // do the send complete.
+ //
+ if (Status != NDIS_STATUS_PENDING) {
+
+ NdisWanSendCompleteHandler(NULL,
+ WanPacket,
+ NDIS_STATUS_SUCCESS);
+
+ Status = NDIS_STATUS_PENDING;
+ }
+ }
+
+ NdisWanDbgOut(DBG_TRACE, DBG_SEND, ("FrameAndSend: Exit"));
+
+ return (Status);
+}
+
+#ifdef BANDWIDTH_ON_DEMAND
+
+BOOLEAN
+IsProtocolQuotaFilled(
+ PPROTOCOLCB ProtocolCB
+ )
+/*++
+
+Routine Name:
+
+ IsProtocolQuotaFilled
+
+Routine Description:
+
+ This routine checks to see if the protocol has filled it's
+ bandwidth quota.
+
+Arguments:
+
+ ProtocolCB - Pointer to the protocolcb that is sending.
+
+Return Values:
+
+ TRUE Quota filled
+ FALSE Quota not filled
+
+--*/
+{
+ BOOLEAN QuotaMet = FALSE;
+ PSAMPLE_TABLE SampleTable = &ProtocolCB->SampleTable;
+ PSEND_SAMPLE FirstSample, CurrentSample;
+
+ AgeSampleTable(SampleTable);
+ if (ProtocolCB->ulByteQuota < SampleTable->ulCurrentSampleByteCount) {
+ QuotaMet = TRUE;
+ }
+
+ return (QuotaMet);
+}
+
+VOID
+AgeSampleTable(
+ PSAMPLE_TABLE SampleTable
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ WAN_TIME CurrentTime, TimeDiff;
+ ULONG FirstIndex = SampleTable->ulFirstIndex;
+ ULONG CurrentIndex = SampleTable->ulCurrentIndex;
+ PSEND_SAMPLE FirstSample = &SampleTable->SampleArray[FirstIndex];
+
+ //
+ // Should return CurrentTime in 100ns units
+ //
+ NdisWanGetSystemTime(&CurrentTime);
+
+ //
+ // We will search through the sample indexing over samples that are more than
+ // one second older than the current time.
+ //
+ NdisWanCalcTimeDiff(&TimeDiff, &CurrentTime, &FirstSample->TimeStamp);
+
+ while ( !NdisWanIsTimeDiffLess(&TimeDiff, &SampleTable->SamplePeriod) &&
+ (FirstIndex != CurrentIndex) ) {
+
+ SampleTable->ulCurrentSampleByteCount -= FirstSample->ulBytesThisSend;
+
+ ASSERT((LONG)SampleTable->ulCurrentSampleByteCount >= 0);
+
+ FirstSample->ulReferenceCount = 0;
+
+ if (++FirstIndex == SampleTable->ulSampleArraySize) {
+ FirstIndex = 0;
+ }
+
+ SampleTable->ulFirstIndex = FirstIndex ;
+
+ FirstSample = &SampleTable->SampleArray[FirstIndex];
+
+ NdisWanCalcTimeDiff(&TimeDiff, &CurrentTime, &FirstSample->TimeStamp);
+ }
+
+}
+
+BOOLEAN
+IsSampleTableFull(
+ PSAMPLE_TABLE SampleTable
+ )
+{
+ LONG Diff;
+
+// AgeSampleTable(SampleTable);
+ Diff = (LONG)(SampleTable->ulCurrentIndex - SampleTable->ulFirstIndex);
+ return((Diff == (LONG)(SampleTable->ulSampleArraySize - 1)) || (Diff == -1));
+}
+
+VOID
+UpdateSampleTable(
+ PSAMPLE_TABLE SampleTable,
+ ULONG BytesSent
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ WAN_TIME CurrentTime, TimeDiff;
+ ULONG CurrentIndex = SampleTable->ulCurrentIndex;
+ PSEND_SAMPLE CurrentSample = &SampleTable->SampleArray[CurrentIndex];
+
+ NdisWanGetSystemTime(&CurrentTime);
+
+ NdisWanCalcTimeDiff(&TimeDiff, &CurrentTime, &CurrentSample->TimeStamp);
+
+ if ( NdisWanIsTimeDiffLess(&TimeDiff, &SampleTable->SampleRate) ||
+ IsSampleTableFull(SampleTable)) {
+ //
+ // Add this send on the previous sample
+ //
+ CurrentSample->ulBytesThisSend += BytesSent;
+ CurrentSample->ulReferenceCount++;
+ } else {
+ //
+ // We need a new sample
+ //
+ if (++CurrentIndex == SampleTable->ulSampleArraySize) {
+ CurrentIndex = 0;
+ }
+
+ SampleTable->ulCurrentIndex = CurrentIndex;
+ CurrentSample = &SampleTable->SampleArray[CurrentIndex];
+ CurrentSample->TimeStamp = CurrentTime;
+ CurrentSample->ulBytesThisSend = BytesSent;
+ CurrentSample->ulReferenceCount = 1;
+ }
+
+ SampleTable->ulCurrentSampleByteCount += BytesSent;
+
+}
+
+VOID
+UpdateBandwidthOnDemand(
+ PBUNDLECB BundleCB,
+ ULONG BytesSent
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ ULONG EventCount;
+ PSAMPLE_TABLE UpperSampleTable = &BundleCB->UpperBonDInfo.SampleTable;
+ PSAMPLE_TABLE LowerSampleTable = &BundleCB->LowerBonDInfo.SampleTable;
+
+ //
+ // Age and update the sample table
+ //
+ AgeSampleTable(UpperSampleTable);
+ UpdateSampleTable(UpperSampleTable, BytesSent);
+ AgeSampleTable(LowerSampleTable);
+ UpdateSampleTable(LowerSampleTable, BytesSent);
+
+ GetGlobalListCount(ThresholdEventQueue, EventCount);
+
+ if (EventCount != 0) {
+
+ CheckUpperThreshold(BundleCB);
+ CheckLowerThreshold(BundleCB);
+
+ }
+
+}
+
+VOID
+CheckUpperThreshold(
+ PBUNDLECB BundleCB
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ WAN_TIME CurrentTime, TimeDiff;
+ PBOND_INFO BonDInfo = &BundleCB->UpperBonDInfo;
+ PSAMPLE_TABLE SampleTable = &BonDInfo->SampleTable;
+ ULONG Bps = SampleTable->ulCurrentSampleByteCount;
+ //
+ // Switch on the current state
+ //
+ switch (BonDInfo->State) {
+ case BonDIdle:
+ //
+ // We are currently below the upper threshold. If we
+ // go over the upperthreshold we will set the time and
+ // transition to the monitor state.
+ //
+ if (Bps >= BonDInfo->ulBytesThreshold) {
+ NdisWanGetSystemTime(&BonDInfo->StartTime);
+ BonDInfo->State = BonDMonitor;
+ }
+ break;
+
+ case BonDMonitor:
+
+ //
+ // We are currently in the monitor state which means that
+ // we have gone above the upper threshold. If we fall below
+ // the upper threshold we will go back to the idle state.
+ //
+ if (Bps < BonDInfo->ulBytesThreshold) {
+ BonDInfo->State = BonDIdle;
+
+ } else {
+
+ NdisWanGetSystemTime(&CurrentTime);
+
+ NdisWanCalcTimeDiff(&TimeDiff, &CurrentTime, &BonDInfo->StartTime);
+
+ if (!NdisWanIsTimeDiffLess(&TimeDiff, &SampleTable->SamplePeriod)) {
+ //
+ // We have been above the threshold for time greater than the
+ // threshold sample period so we need to notify someone of this
+ // historic event!
+ //
+ CompleteThresholdEvent(BundleCB, UPPER_THRESHOLD);
+
+ //
+ // I'm not sure what state we should be in now!
+ //
+ BonDInfo->State = BonDSignaled;
+ }
+ }
+ break;
+
+ case BonDSignaled:
+ break;
+
+ }
+}
+
+VOID
+CheckLowerThreshold(
+ PBUNDLECB BundleCB
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ WAN_TIME CurrentTime, TimeDiff;
+ PBOND_INFO BonDInfo = &BundleCB->LowerBonDInfo;
+ PSAMPLE_TABLE SampleTable = &BonDInfo->SampleTable;
+ ULONG Bps = SampleTable->ulCurrentSampleByteCount;
+
+ //
+ // Switch on the current state
+ //
+ switch (BonDInfo->State) {
+ case BonDIdle:
+ //
+ // We are currently above the lower threshold. If we
+ // go below the lowerthreshold we will set the time and
+ // transition to the monitor state.
+ //
+ if (Bps <= BonDInfo->ulBytesThreshold) {
+ NdisWanGetSystemTime(&BonDInfo->StartTime);
+ BonDInfo->State = BonDMonitor;
+ }
+ break;
+
+ case BonDMonitor:
+
+ //
+ // We are currently in the monitor state which means that
+ // we have gone below the lower threshold. If we rise above
+ // the lower threshold we will go back to the idle state.
+ //
+ if (Bps > BonDInfo->ulBytesThreshold) {
+ BonDInfo->State = BonDIdle;
+
+ } else {
+
+ NdisWanGetSystemTime(&CurrentTime);
+
+ NdisWanCalcTimeDiff(&TimeDiff, &CurrentTime, &BonDInfo->StartTime);
+
+ if (!NdisWanIsTimeDiffLess(&TimeDiff, &SampleTable->SamplePeriod)) {
+ //
+ // We have been below the lower threshold for time greater than the
+ // threshold sample period so we need to notify someone of this
+ // historic event!
+ //
+ CompleteThresholdEvent(BundleCB, LOWER_THRESHOLD);
+
+ //
+ // I'm not sure what state we should be in now!
+ //
+ BonDInfo->State = BonDSignaled;
+ }
+ }
+ break;
+
+ case BonDSignaled:
+ break;
+
+ }
+}
+
+#endif // end of BANDWIDTH_ON_DEMAND
+
+PLINKCB
+GetNextLinkToXmitOn(
+ PBUNDLECB BundleCB
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ PLINKCB LinkCB = BundleCB->NextLinkToXmit;
+ PLIST_ENTRY LinkCBList = &BundleCB->LinkCBList;
+
+ //
+ // We need to find the first link that has an open send window
+ //
+ while (LinkCB->ulWanPacketCount < 2) {
+ LinkCB = (PLINKCB)LinkCB->Linkage.Flink;
+
+ if ((PVOID)LinkCB == (PVOID)LinkCBList) {
+ LinkCB = (PLINKCB)LinkCBList->Flink;
+ }
+ }
+
+ BundleCB->NextLinkToXmit =
+ ((PVOID)LinkCB->Linkage.Flink == (PVOID)LinkCBList) ?
+ (PLINKCB)LinkCBList->Flink : (PLINKCB)LinkCB->Linkage.Flink;
+
+ LinkCB->OutstandingFrames++;
+
+ return(LinkCB);
+}
+
+NDIS_STATUS
+BuildIoPacket(
+ IN PNDISWAN_IO_PACKET pWanIoPacket,
+ IN BOOLEAN SendImmediate
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ NDIS_STATUS Status = NDIS_STATUS_RESOURCES;
+ PWAN_IO_PROTOCOL_RESERVED pProtocolReserved;
+ PPROTOCOLCB ProtocolCB;
+ ULONG Stage = 0, ulAllocationSize = 0;
+ PUCHAR pAllocatedMemory = NULL, pSrcAddr, pDestAddr;
+ NDIS_HANDLE hPacketPool, hBufferPool, hBundle, hLink;
+ PNDIS_PACKET pNdisPacket;
+ PNDIS_BUFFER pNdisBuffer;
+ PBUNDLECB BundleCB;
+ PLINKCB LinkCB = NULL;
+ UCHAR SendHeader[] = {' ', 'S', 'E', 'N', 'D', 0xFF};
+
+ NdisWanDbgOut(DBG_TRACE, DBG_SEND, ("BuildIoPacket: Enter!"));
+ //
+ // Some time in the future this should be redone so that
+ // there is a pool of packets and buffers attached to a
+ // BundleCB. This pool could be grown and shrunk as needed
+ // but some minimum number would live for the lifetime of
+ // the BundleCB.
+
+ if (pWanIoPacket->usHandleType == LINKHANDLE) {
+
+ hLink = pWanIoPacket->hHandle;
+ LINKCB_FROM_LINKH(LinkCB, hLink);
+
+ if (LinkCB == NULL) {
+ return (NDIS_STATUS_SUCCESS);
+ }
+
+ BundleCB = LinkCB->BundleCB;
+
+ if (BundleCB == NULL) {
+ return (NDIS_STATUS_SUCCESS);
+ }
+
+ } else {
+ hBundle = pWanIoPacket->hHandle;
+ BUNDLECB_FROM_BUNDLEH(BundleCB, hBundle);
+
+ if (BundleCB == NULL) {
+ return (NDIS_STATUS_SUCCESS);
+ }
+
+ LinkCB = (PLINKCB)BundleCB->LinkCBList.Flink;
+
+ if (LinkCB == NULL) {
+ return (NDIS_STATUS_SUCCESS);
+ }
+ }
+
+ NdisAcquireSpinLock(&BundleCB->Lock);
+
+ if ((LinkCB->State != LINK_UP) ||
+ (BundleCB->State != BUNDLE_UP)) {
+ NdisReleaseSpinLock(&BundleCB->Lock);
+ return (NDIS_STATUS_SUCCESS);
+ }
+
+ //
+ // We only support ethernet headers right now so the supplied header
+ // either has to be ethernet or none at all!
+ //
+
+ //
+ //
+ // Get an NdisPacket for this send
+ //
+ NdisAllocatePacketPool(&Status,
+ &hPacketPool,
+ 1,
+ sizeof(WAN_IO_PROTOCOL_RESERVED));
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+ NdisWanDbgOut(DBG_FAILURE, DBG_SEND, ("BuildIoPacket: Error Allocating PacketPool!"));
+ NdisReleaseSpinLock(&BundleCB->Lock);
+ goto RESOURCE_ERROR;
+ }
+
+ Stage++;
+
+ NdisAllocatePacket(&Status,
+ &pNdisPacket,
+ hPacketPool);
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+ NdisWanDbgOut(DBG_FAILURE, DBG_SEND, ("BuildIoPacket: Error Allocating Packet!"));
+ NdisReleaseSpinLock(&BundleCB->Lock);
+ goto RESOURCE_ERROR;
+ }
+
+ Stage++;
+
+ //
+ // Get an NdisBuffer for this send
+ //
+ NdisAllocateBufferPool(&Status,
+ &hBufferPool,
+ 2);
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+ NdisWanDbgOut(DBG_FAILURE, DBG_SEND, ("BuildIoPacket: Error Allocating BufferPool!"));
+ NdisReleaseSpinLock(&BundleCB->Lock);
+ goto RESOURCE_ERROR;
+ }
+
+ Stage++;
+
+ if (pWanIoPacket->usHeaderSize == 0) {
+ ulAllocationSize = 12;
+ }
+
+ ulAllocationSize += pWanIoPacket->usPacketSize;
+
+ NdisWanAllocateMemory(&pAllocatedMemory, ulAllocationSize);
+
+ if (pAllocatedMemory == NULL) {
+ NdisWanDbgOut(DBG_FAILURE, DBG_SEND, ("BuildIoPacket: Error Allocating Memory! Size: %d", ulAllocationSize));
+ NdisReleaseSpinLock(&BundleCB->Lock);
+ goto RESOURCE_ERROR;
+ }
+
+ Stage++;
+
+ NdisAllocateBuffer(&Status,
+ &pNdisBuffer,
+ hBufferPool,
+ pAllocatedMemory,
+ ulAllocationSize);
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+ NdisWanDbgOut(DBG_FAILURE, DBG_SEND, ("BuildIoPacket: Error Allocating Buffer!"));
+ NdisReleaseSpinLock(&BundleCB->Lock);
+ goto RESOURCE_ERROR;
+ }
+
+ Stage++;
+
+ pProtocolReserved = (PWAN_IO_PROTOCOL_RESERVED)pNdisPacket->ProtocolReserved;
+ pProtocolReserved->LinkCB = LinkCB;
+ pProtocolReserved->hPacketPool = hPacketPool;
+ pProtocolReserved->pNdisPacket = pNdisPacket;
+ pProtocolReserved->hBufferPool = hBufferPool;
+ pProtocolReserved->pNdisBuffer = pNdisBuffer;
+ pProtocolReserved->pAllocatedMemory = pAllocatedMemory;
+ pProtocolReserved->ulAllocationSize = ulAllocationSize;
+
+ pDestAddr = &pAllocatedMemory[0];
+ pSrcAddr = &pAllocatedMemory[6];
+
+ //
+ // If no header build a header
+ //
+ if (pWanIoPacket->usHeaderSize == 0) {
+
+ //
+ // Header will look like " S XXYYYY" where
+ // XX is the ProtocolCB index and YYYY is the
+ // BundleCB index. Both the Src and Dst addresses
+ // look the same.
+ //
+ NdisMoveMemory(pDestAddr,
+ SendHeader,
+ sizeof(SendHeader));
+
+ NdisMoveMemory(pSrcAddr,
+ SendHeader,
+ sizeof(SendHeader));
+
+ } else {
+ //
+ // Header supplied so go ahead and move it.
+ //
+ NdisMoveMemory(pDestAddr,
+ pWanIoPacket->PacketData,
+ pWanIoPacket->usHeaderSize);
+ }
+
+ //
+ // Fill the BundleCB Index for the Src and Dest Address
+ //
+ FillNdisWanProtocolIndex(pDestAddr, hLink);
+ FillNdisWanProtocolIndex(pSrcAddr, hLink);
+
+ //
+ // Copy the data to the buffer
+ //
+ NdisMoveMemory(&pAllocatedMemory[12],
+ &pWanIoPacket->PacketData[pWanIoPacket->usHeaderSize],
+ pWanIoPacket->usPacketSize);
+
+ //
+ // Chain buffer to ndis packet
+ //
+ NdisChainBufferAtFront(pNdisPacket, pNdisBuffer);
+
+ //
+ // Queue the packet on the bundlecb
+ //
+ ProtocolCB = BundleCB->ProtocolCBTable[0];
+
+ ASSERT(ProtocolCB != NULL);
+
+ if (SendImmediate) {
+ InsertHeadNdisPacketQueue(ProtocolCB, pNdisPacket);
+ } else {
+ InsertTailNdisPacketQueue(ProtocolCB, pNdisPacket);
+ }
+
+ //
+ // Try to send
+ //
+ // Called with lock held and returns with
+ // lock released
+ //
+ Status = SendPacketOnBundle(BundleCB);
+
+ //
+ // We don't pend I/O packets so complete
+ // as if it succeeded
+ //
+ if (Status == NDIS_STATUS_PENDING) {
+ Status = NDIS_STATUS_SUCCESS;
+ }
+
+ if (Status != NDIS_STATUS_SUCCESS) {
+
+RESOURCE_ERROR:
+
+ //
+ // Free all of the allocated resources
+ //
+ switch (Stage) {
+ case 5:
+ NdisFreeBuffer(pNdisBuffer);
+
+ case 4:
+ NdisWanFreeMemory(pAllocatedMemory);
+
+ case 3:
+ NdisFreeBufferPool(hBufferPool);
+
+ case 2:
+ NdisFreePacket(pNdisPacket);
+
+ case 1:
+ NdisFreePacketPool(hPacketPool);
+
+ }
+ }
+
+ NdisWanDbgOut(DBG_TRACE, DBG_SEND, ("BuildIoPacket: Exit-Status: 0x%8.8x\n", Status));
+
+ return (Status);
+}
+
+//ULONG
+//GetNumSendingLinks(
+// PBUNDLECB BundleCB
+// )
+///*++
+//
+//Routine Name:
+//
+//Routine Description:
+//
+//Arguments:
+//
+//Return Values:
+//
+//--*/
+//{
+// ULONG LinkCount = 0;
+// PLINKCB LinkCB;
+//
+// //
+// // We need to walk through the list of links on this bundle and
+// // count how many have an open send window.
+// //
+// for (LinkCB = (PLINKCB)BundleCB->LinkCBList.Flink;
+// (PVOID)LinkCB != (PVOID)&BundleCB->LinkCBList;
+// LinkCB = (PLINKCB)LinkCB->Linkage.Flink) {
+//
+// //
+// // Since we create enough sendwindow + 1 wanpackets
+// // for each link, if the send window is open we will
+// // have atleast 2 wanpackets available.
+// //
+// if (LinkCB->ulWanPacketCount > 1) {
+// LinkCount++;
+// }
+// }
+//
+// return (LinkCount);
+//}
+
+VOID
+BuildLinkHeader(
+ PHEADER_FRAMING_INFO FramingInfo,
+ PUCHAR StartBuffer
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ ULONG LinkFraming = FramingInfo->FramingBits;
+ ULONG Flags = FramingInfo->Flags;
+ PUCHAR CurrentPointer = StartBuffer;
+
+ FramingInfo->HeaderLength =
+ FramingInfo->AddressControl.Length =
+ FramingInfo->Multilink.Length =
+ FramingInfo->Compression.Length =
+ FramingInfo->ProtocolID.Length = 0;
+
+ if (LinkFraming & PPP_FRAMING) {
+
+ if (!(LinkFraming & PPP_COMPRESS_ADDRESS_CONTROL)) {
+ //
+ // If there is no address/control compression
+ // we need a pointer and a length
+ //
+ FramingInfo->AddressControl.Pointer = CurrentPointer;
+ *CurrentPointer++ = 0xFF;
+ *CurrentPointer++ = 0x03;
+ FramingInfo->AddressControl.Length = 2;
+ FramingInfo->HeaderLength += FramingInfo->AddressControl.Length;
+
+ }
+
+ if (!(Flags & IO_PROTOCOLID)) {
+
+ //
+ // If this is not from our private I/O interface we will
+ // build the rest of the header.
+ //
+ if ((Flags & DO_MULTILINK) && (LinkFraming & PPP_MULTILINK_FRAMING)) {
+
+ //
+ // We are doing multilink so we need a pointer
+ // and a length
+ //
+ FramingInfo->Multilink.Pointer = CurrentPointer;
+
+ if (!(LinkFraming & PPP_COMPRESS_PROTOCOL_FIELD)) {
+ //
+ // No protocol compression
+ //
+ *CurrentPointer++ = 0x00;
+ FramingInfo->Multilink.Length++;
+ }
+
+ *CurrentPointer++ = 0x3D;
+ FramingInfo->Multilink.Length++;
+
+ if (!(LinkFraming & PPP_SHORT_SEQUENCE_HDR_FORMAT)) {
+ //
+ // We are using long sequence number
+ //
+ FramingInfo->Multilink.Length += 2;
+ CurrentPointer += 2;
+
+ }
+
+ FramingInfo->Multilink.Length += 2;
+ CurrentPointer += 2;
+
+ FramingInfo->HeaderLength += FramingInfo->Multilink.Length;
+
+ }
+
+ if (Flags & (DO_COMPRESSION | DO_ENCRYPTION)) {
+ //
+ // We are doing compression/encryption so we need
+ // a pointer and a length
+ //
+ FramingInfo->Compression.Pointer = CurrentPointer;
+
+ //
+ // It appears that legacy ras (< NT 4.0) requires that
+ // the PPP protocol field in a compressed packet not
+ // be compressed, ie has to have the leading 0x00
+ //
+ if (!(LinkFraming & PPP_COMPRESS_PROTOCOL_FIELD)) {
+ //
+ // No protocol compression
+ //
+ *CurrentPointer++ = 0x00;
+ FramingInfo->Compression.Length++;
+ }
+
+ *CurrentPointer++ = 0xFD;
+ FramingInfo->Compression.Length++;
+
+ //
+ // Add coherency bytes
+ //
+ FramingInfo->Compression.Length += 2;
+ CurrentPointer += 2;
+
+ FramingInfo->HeaderLength += FramingInfo->Compression.Length;
+ }
+
+ if (Flags & FIRST_FRAGMENT) {
+
+ FramingInfo->ProtocolID.Pointer = CurrentPointer;
+
+ if (!(LinkFraming & PPP_COMPRESS_PROTOCOL_FIELD) ||
+ (Flags & (DO_COMPRESSION | DO_ENCRYPTION))) {
+ FramingInfo->ProtocolID.Length++;
+ CurrentPointer++;
+ }
+
+ FramingInfo->ProtocolID.Length++;
+ FramingInfo->HeaderLength += FramingInfo->ProtocolID.Length;
+
+ }
+ }
+
+ } else if ((LinkFraming & RAS_FRAMING)) {
+ //
+ // If this is old ras framing:
+ //
+ // Alter the framing so that 0xFF 0x03 is not added
+ // and that the first byte is 0xFD not 0x00 0xFD
+ //
+ // So basically, a RAS compression looks like
+ // <0xFD> <2 BYTE COHERENCY> <NBF DATA FIELD>
+ //
+ // Whereas uncompressed looks like
+ // <NBF DATA FIELD> which always starts with 0xF0
+ //
+ // If this is ppp framing:
+ //
+ // A compressed frame will look like (before address/control
+ // - multilink is added)
+ // <0x00> <0xFD> <2 Byte Coherency> <Compressed Data>
+ //
+ if (Flags & (DO_COMPRESSION | DO_ENCRYPTION)) {
+ FramingInfo->Compression.Pointer = CurrentPointer;
+
+ *CurrentPointer++ = 0xFD;
+ FramingInfo->Compression.Length++;
+
+ //
+ // Coherency bytes
+ //
+ FramingInfo->Compression.Length += 2;
+ CurrentPointer += 2;
+
+ FramingInfo->HeaderLength += FramingInfo->Compression.Length;
+ }
+ }
+}
+
+VOID
+NdisWanCopyFromPacketToBuffer(
+ IN PNDIS_PACKET pNdisPacket,
+ IN ULONG Offset,
+ IN ULONG BytesToCopy,
+ OUT PUCHAR Buffer,
+ OUT PULONG BytesCopied
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ ULONG NdisBufferCount;
+ PNDIS_BUFFER CurrentBuffer;
+ PVOID VirtualAddress;
+ ULONG CurrentLength, AmountToMove;
+ ULONG LocalBytesCopied = 0;
+
+ *BytesCopied = 0;
+
+ //
+ // Take care of zero byte copy
+ //
+ if (!BytesToCopy) {
+ return;
+ }
+
+ //
+ // Get the buffer count
+ //
+ NdisQueryPacket(pNdisPacket,
+ NULL,
+ &NdisBufferCount,
+ &CurrentBuffer,
+ NULL);
+
+ //
+ // Could be a null packet
+ //
+ if (!NdisBufferCount) {
+ return;
+ }
+
+
+ NdisQueryBuffer(CurrentBuffer,
+ &VirtualAddress,
+ &CurrentLength);
+
+ while (LocalBytesCopied < BytesToCopy) {
+
+ //
+ // No more bytes left in this buffer
+ //
+ if (!CurrentLength) {
+
+ //
+ // Get the next buffer
+ //
+ NdisGetNextBuffer(CurrentBuffer,
+ &CurrentBuffer);
+
+ //
+ // End of the packet, copy what we can
+ //
+ if (CurrentBuffer == NULL) {
+ break;
+ }
+
+ //
+ //
+ //
+ NdisQueryBuffer(CurrentBuffer,
+ &VirtualAddress,
+ &CurrentLength);
+
+ continue;
+ }
+
+ //
+ // Get to the point where we can start copying
+ //
+ if (Offset) {
+
+ if (Offset > CurrentLength) {
+
+ //
+ // Not in this buffer, go to the next one
+ //
+ Offset -= CurrentLength;
+ CurrentLength = 0;
+ continue;
+
+ } else {
+
+ //
+ // At least some in this buffer
+ //
+ VirtualAddress = (PUCHAR)VirtualAddress + Offset;
+ CurrentLength -= Offset;
+ Offset = 0;
+ }
+
+ }
+
+ //
+ // We can copy some data. If we need more data than is available
+ // in this buffer we can copy what we need and go back for more.
+ //
+ AmountToMove = (CurrentLength > (BytesToCopy - LocalBytesCopied)) ?
+ (BytesToCopy - LocalBytesCopied) : CurrentLength;
+
+ NdisMoveMemory(Buffer, VirtualAddress, AmountToMove);
+
+ Buffer = (PUCHAR)Buffer + AmountToMove;
+
+ VirtualAddress = (PUCHAR)VirtualAddress + AmountToMove;
+
+ LocalBytesCopied += AmountToMove;
+
+ CurrentLength -= AmountToMove;
+
+ }
+
+ *BytesCopied = LocalBytesCopied;
+}
+
+PNDIS_WAN_PACKET
+GetWanPacketFromLink(
+ PLINKCB LinkCB
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ PNDIS_WAN_PACKET WanPacket;
+ ULONG PrevCount = LinkCB->ulWanPacketCount;
+
+ ASSERT(LinkCB->ulWanPacketCount);
+
+ //
+ // If the current count is greater than threshold and the
+ // new count falls below we need to decrement the sending
+ // link count.
+ //
+ if ((--LinkCB->ulWanPacketCount < 2) && (PrevCount > 1)) {
+ ((PBUNDLECB)LinkCB->BundleCB)->SendingLinks--;
+ }
+
+ WanPacket = (PNDIS_WAN_PACKET)RemoveHeadList(&LinkCB->WanPacketPool);
+
+ return (WanPacket);
+}
+
+VOID
+ReturnWanPacketToLink(
+ PLINKCB LinkCB,
+ PNDIS_WAN_PACKET WanPacket
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ ULONG PrevCount = LinkCB->ulWanPacketCount;
+
+ //
+ // If the current count is below the threshold and the
+ // new count puts us over we need to increment the sending
+ // link count.
+ //
+ if ((++LinkCB->ulWanPacketCount > 1) && (PrevCount < 2)) {
+ ((PBUNDLECB)LinkCB->BundleCB)->SendingLinks++;
+ }
+
+ InsertTailList(&LinkCB->WanPacketPool, &WanPacket->WanPacketQueue);
+}
+
+VOID
+DestroyIoPacket(
+ PNDIS_PACKET NdisPacket
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ PWAN_IO_PROTOCOL_RESERVED ProtocolReserved =
+ (PWAN_IO_PROTOCOL_RESERVED)NdisPacket->ProtocolReserved;
+
+ NDIS_HANDLE PacketPool = ProtocolReserved->hPacketPool;
+
+ NdisWanFreeMemory(ProtocolReserved->pAllocatedMemory);
+ NdisFreeBuffer(ProtocolReserved->pNdisBuffer);
+ NdisFreeBufferPool(ProtocolReserved->hBufferPool);
+ NdisFreePacket(NdisPacket);
+ NdisFreePacketPool(PacketPool);
+}
+
+#if DBG
+VOID
+InsertDbgPacket(
+ PDBG_SEND_CONTEXT DbgContext
+ )
+{
+ PDBG_SEND_PACKET DbgPacket;
+ PBUNDLECB BundleCB = DbgContext->BundleCB;
+ PPROTOCOLCB ProtocolCB = DbgContext->ProtocolCB;
+ PLINKCB LinkCB = DbgContext->LinkCB;
+
+ NdisWanAllocateMemory(&DbgPacket, sizeof(DBG_SEND_PACKET));
+
+ if (DbgPacket == NULL) {
+ return;
+ }
+
+ DbgPacket->Packet = DbgContext->Packet;
+ DbgPacket->PacketType = DbgContext->PacketType;
+ DbgPacket->BundleCB = BundleCB;
+ if (BundleCB) {
+ DbgPacket->BundleState = BundleCB->State;
+ DbgPacket->BundleFlags = BundleCB->Flags;
+ }
+
+ DbgPacket->ProtocolCB = ProtocolCB;
+ if (ProtocolCB) {
+ DbgPacket->ProtocolFlags = ProtocolCB->Flags;
+ }
+
+ DbgPacket->LinkCB = LinkCB;
+ if (LinkCB) {
+ DbgPacket->LinkState = LinkCB->State;
+ }
+
+ NdisAcquireSpinLock(DbgContext->ListLock);
+ InsertTailList(DbgContext->ListHead, &DbgPacket->Linkage);
+ NdisReleaseSpinLock(DbgContext->ListLock);
+}
+
+BOOLEAN
+RemoveDbgPacket(
+ PDBG_SEND_CONTEXT DbgContext
+ )
+{
+ PDBG_SEND_PACKET DbgPacket = NULL;
+ BOOLEAN Found = FALSE;
+
+ NdisAcquireSpinLock(DbgContext->ListLock);
+
+ if (!IsListEmpty(DbgContext->ListHead)) {
+ for (DbgPacket = (PDBG_SEND_PACKET)DbgContext->ListHead->Flink;
+ (PVOID)DbgPacket != (PVOID)DbgContext->ListHead;
+ DbgPacket = (PDBG_SEND_PACKET)DbgPacket->Linkage.Flink) {
+
+ if (DbgPacket->Packet == DbgContext->Packet) {
+ RemoveEntryList(&DbgPacket->Linkage);
+ NdisWanFreeMemory(DbgPacket);
+ Found = TRUE;
+ break;
+ }
+
+ }
+ }
+
+ ASSERT(Found == TRUE);
+
+ NdisReleaseSpinLock(DbgContext->ListLock);
+
+ return (Found);
+}
+
+#endif
diff --git a/private/ntos/ndis/ndiswan/tapi.c b/private/ntos/ndis/ndiswan/tapi.c
new file mode 100644
index 000000000..bc1c4cb6e
--- /dev/null
+++ b/private/ntos/ndis/ndiswan/tapi.c
@@ -0,0 +1,144 @@
+/*++
+
+Copyright (c) 1990-1995 Microsoft Corporation
+
+Module Name:
+
+ Tapi.c
+
+Abstract:
+
+
+Author:
+
+ Tony Bell (TonyBe) June 06, 1995
+
+Environment:
+
+ Kernel Mode
+
+Revision History:
+
+ TonyBe 06/06/95 Created
+
+--*/
+
+
+//
+// We want to initialize all of the global variables now!
+//
+#include "wan.h"
+
+EXPORT
+VOID
+NdisTapiCompleteRequest(
+ IN NDIS_HANDLE Handle,
+ IN PVOID NdisRequest,
+ IN NDIS_STATUS Status
+ );
+
+EXPORT
+VOID
+NdisTapiIndicateStatus(
+ IN NDIS_HANDLE Handle,
+ IN PVOID StatusBuffer,
+ IN UINT StatusBufferSize
+ );
+
+
+NDIS_STATUS
+NdisWanTapiRequestProc(
+ PWAN_ADAPTERCB WanAdapterCB,
+ PNDIS_REQUEST NdisRequest
+ )
+/*++
+
+Routine Name:
+
+ NdisWanTapiRequestProc
+
+Routine Description:
+
+ Procedure is called by the NdisTapi.sys driver to send
+ requests to the WanMiniport driver. We intercept this
+ just to moderate. NdisTapi could call the miniport directly
+ if we wanted but we don't.
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ NDIS_STATUS Status;
+
+ NdisWanDbgOut(DBG_TRACE, DBG_TAPI, ("NdisWanTapiRequestProc - Enter"));
+ NdisWanDbgOut(DBG_INFO, DBG_TAPI, ("NdisRequest: Type: 0x%8.8x OID: 0x%8.8x",
+ NdisRequest->RequestType,NdisRequest->DATA.QUERY_INFORMATION.Oid));
+
+ Status = NdisWanSubmitNdisRequest(WanAdapterCB,
+ NdisRequest,
+ ASYNC,
+ NDISTAPI);
+
+ NdisWanDbgOut(DBG_INFO, DBG_TAPI, ("Status: 0x%8.8x", Status));
+ NdisWanDbgOut(DBG_TRACE, DBG_TAPI, ("NdisWanTapiRequestProc - Exit"));
+
+ return (Status);
+}
+
+VOID
+NdisWanTapiRequestComplete(
+ PWAN_ADAPTERCB WanAdapterCB,
+ PWAN_REQUEST WanRequest
+ )
+{
+ NdisWanDbgOut(DBG_TRACE, DBG_TAPI, ("NdisWanTapiRequestComplete - Enter"));
+ NdisWanDbgOut(DBG_INFO, DBG_TAPI, ("NdisRequest: Type: 0x%8.8x OID: 0x%8.8x",
+ WanRequest->pNdisRequest->RequestType,
+ WanRequest->pNdisRequest->DATA.QUERY_INFORMATION.Oid));
+ NdisWanDbgOut(DBG_INFO, DBG_TAPI, ("Status: 0x%8.8x",
+ WanRequest->NotificationStatus));
+
+ RemoveRequestFromList(WanAdapterCB, WanRequest);
+
+ NdisTapiCompleteRequest(WanAdapterCB,
+ WanRequest->pNdisRequest,
+ WanRequest->NotificationStatus);
+
+ NdisWanFreeMemory(WanRequest);
+}
+
+VOID
+NdisWanTapiIndication(
+ PWAN_ADAPTERCB WanAdapterCB,
+ PUCHAR StatusBuffer,
+ ULONG StatusBufferSize
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ NdisWanDbgOut(DBG_TRACE, DBG_TAPI, ("NdisWanTapiIndication - Enter"));
+
+ //
+ // If tapi is present and this miniport has registered for
+ // connectionwrapper services give this to tapi
+ //
+ if (WanAdapterCB->WanInfo.FramingBits & TAPI_PROVIDER) {
+
+ NdisTapiIndicateStatus(WanAdapterCB,
+ StatusBuffer,
+ StatusBufferSize);
+ }
+
+ NdisWanDbgOut(DBG_TRACE, DBG_TAPI, ("NdisWanTapiIndication - Exit"));
+}
diff --git a/private/ntos/ndis/ndiswan/tcpip.h b/private/ntos/ndis/ndiswan/tcpip.h
new file mode 100644
index 000000000..de5abe474
--- /dev/null
+++ b/private/ntos/ndis/ndiswan/tcpip.h
@@ -0,0 +1,52 @@
+// TCP control bits
+
+#ifndef _TCPIP_
+#define _TCPIP_
+
+#define TH_SYN 0x02 // Synchronize sequence numbers
+#define TH_FIN 0x01 // Sender has reached end of his stream
+#define TH_RST 0x04 // Reset the connection
+#define TH_PUSH 0x08 // Push data to above level
+#define TH_ACK 0x10 // Acknowledgement field is valid
+#define TH_URG 0x20 // Urgent pointer is valid
+
+struct tcphdr {
+ USHORT th_sport;
+ USHORT th_dport;
+ ULONG th_seq;
+ ULONG th_ack;
+ UCHAR th_off;
+ UCHAR th_flags;
+ USHORT th_win;
+ UCHAR th_sumhi;
+ UCHAR th_sumlo;
+ USHORT th_urp;
+ UCHAR th_data[1];
+};
+
+#define IP_ALEN 4
+
+typedef struct IPaddr {
+ ULONG s_addr;
+} IPaddr;
+
+#define IPPROTO_TCP 6
+
+struct ip {
+
+ UCHAR ip_hl;
+ UCHAR ip_tos;
+ USHORT ip_len;
+ USHORT ip_id;
+ USHORT ip_off;
+ UCHAR ip_ttl;
+ UCHAR ip_p;
+ USHORT ip_sum;
+ IPaddr ip_src;
+ IPaddr ip_dst;
+ UCHAR ip_data[1];
+};
+
+typedef struct ip IPHeader, *PIPHeader;
+
+#endif // _TCPIP_
diff --git a/private/ntos/ndis/ndiswan/util.c b/private/ntos/ndis/ndiswan/util.c
new file mode 100644
index 000000000..a44cb40ea
--- /dev/null
+++ b/private/ntos/ndis/ndiswan/util.c
@@ -0,0 +1,323 @@
+/*++
+
+Copyright (c) 1990-1995 Microsoft Corporation
+
+Module Name:
+
+ Util.c
+
+Abstract:
+
+This file contains utility functions used by NdisWan.
+
+Author:
+
+ Tony Bell (TonyBe) June 06, 1995
+
+Environment:
+
+ Kernel Mode
+
+Revision History:
+
+ TonyBe 06/06/95 Created
+
+--*/
+
+#include "wan.h"
+
+#ifdef NT
+
+
+VOID
+NdisWanStringToNdisString(
+ PNDIS_STRING pDestString,
+ PWSTR pSrcBuffer
+ )
+{
+ PWSTR Dest, Src = pSrcBuffer;
+ NDIS_STRING SrcString;
+
+ RtlInitUnicodeString(&SrcString, pSrcBuffer);
+ NdisWanAllocateMemory(&pDestString->Buffer, SrcString.MaximumLength);
+ pDestString->MaximumLength = SrcString.MaximumLength;
+ pDestString->Length = SrcString.Length;
+ RtlCopyUnicodeString(pDestString, &SrcString);
+}
+
+//VOID
+//NdisWanInitNdisString(
+// PNDIS_STRING pDestString,
+// PWSTR pSrcBuffer,
+// USHORT ulSrcLength
+// )
+//{
+// PWSTR Dest, Src = pSrcBuffer;
+//
+// pDestString->Length = ulSrcLength;
+// pDestString->MaximumLength = pDestString->Length + 1;
+//
+// NdisAllocateMemory((PVOID)&(pDestString->Buffer),
+// (pDestString->MaximumLength * sizeof(WCHAR)),
+// 0,
+// HighestAcceptableAddress);
+//
+// Dest = pDestString->Buffer;
+// Src = pSrcBuffer;
+//
+// while (ulSrcLength--) {
+// *Dest = *Src;
+// Dest++;
+// Src++;
+// }
+//
+// *Dest = UNICODE_NULL;
+//}
+
+VOID
+NdisWanFreeNdisString(
+ PNDIS_STRING NdisString
+ )
+{
+ NdisWanFreeMemory(NdisString->Buffer);
+}
+
+VOID
+NdisWanAllocateAdapterName(
+ PNDIS_STRING Dest,
+ PNDIS_STRING Src
+ )
+{
+ NdisWanAllocateMemory(&Dest->Buffer, Src->MaximumLength);
+ Dest->MaximumLength = Src->MaximumLength;
+ Dest->Length = Src->Length;
+ RtlUpcaseUnicodeString(Dest, Src, FALSE);
+}
+
+BOOLEAN
+NdisWanCompareNdisString(
+ PNDIS_STRING NdisString1,
+ PNDIS_STRING NdisString2
+ )
+{
+ USHORT l1 = NdisString1->Length;
+ USHORT l2 = NdisString2->Length;
+ PWSTR s1 = NdisString1->Buffer;
+ PWSTR s2 = NdisString2->Buffer;
+ PWSTR EndCompare;
+
+ ASSERT(l1 != 0);
+ ASSERT(l2 != 0);
+
+ if (l1 == l2) {
+
+ EndCompare = (PWSTR)((PUCHAR)s1 + l1);
+
+ while (s1 < EndCompare) {
+
+ if (*s1++ != *s2++) {
+ return (FALSE);
+
+ }
+ }
+
+ return (TRUE);
+ }
+
+ return(FALSE);
+}
+
+
+//VOID
+//NdisWanFreeNdisString(
+// PNDIS_STRING NdisString
+// )
+//{
+// NdisFreeMemory(NdisString->Buffer,
+// NdisString->MaximumLength * sizeof(WCHAR),
+// 0);
+//}
+
+VOID
+NdisWanNdisStringToInteger(
+ PNDIS_STRING Source,
+ PULONG Value
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ PWSTR s = Source->Buffer;
+ ULONG Digit;
+
+ *Value = 0;
+
+ while (*s != UNICODE_NULL) {
+
+ if (*s >= L'0' && *s < L'9') {
+ Digit = *s - L'0';
+ } else if (*s >= L'A' && *s <= L'F') {
+ Digit = *s - L'A' + 10;
+ } else if (*s >= L'a' && *s <= L'f') {
+ Digit = *s - L'a' + 10;
+ }
+
+ *Value = (*Value << 4) | Digit;
+
+ s++;
+ }
+}
+
+VOID
+NdisWanCopyNdisString(
+ PNDIS_STRING Dest,
+ PNDIS_STRING Src
+ )
+/*++
+
+Routine Name:
+
+Routine Description:
+
+Arguments:
+
+Return Values:
+
+--*/
+{
+ PWSTR SrcBuffer = Src->Buffer;
+ PWSTR DestBuffer = Dest->Buffer;
+
+ while (*SrcBuffer != UNICODE_NULL) {
+
+ *DestBuffer = *SrcBuffer;
+
+ SrcBuffer++;
+ DestBuffer++;
+ }
+
+ *DestBuffer = UNICODE_NULL;
+
+ Dest->Length = Src->Length;
+
+}
+
+#ifndef USE_NDIS_MINIPORT_LOCKING
+
+#define CURRENT_THREAD ((LONG)PsGetCurrentThread())
+BOOLEAN
+NdisWanAcquireMiniportLock(
+ PADAPTERCB AdapterCB
+ )
+/*++
+
+Routine Name:
+
+ NdisWanAcquireMiniportLock
+
+Routine Description:
+
+ This routine does the work that the ndis wrapper would normally do
+ to get a miniport's spinlock and local lock. Called when ndiswan gets
+ an indication from a lower miniport or user mode.
+
+Arguments:
+
+ PADAPTERCB AdapterCB - Miniport context (ndiswan space)
+
+Return Values:
+
+--*/
+{
+ PNDIS_MINIPORT_BLOCK MiniportBlock;
+ BOOLEAN LockAcquired = FALSE;
+ LONG original;
+ KIRQL SavedIrql, MiniportLockIrql;
+
+ MiniportBlock = (PNDIS_MINIPORT_BLOCK)AdapterCB->hMiniportHandle;
+
+ KeRaiseIrql(DISPATCH_LEVEL, &SavedIrql);
+
+ ExAcquireSpinLock(&MiniportBlock->Lock.SpinLock, &MiniportLockIrql);
+
+ //
+ // If the lock is already acquired we may be in a deadlock situation.
+ //
+ if (!MiniportBlock->LockAcquired) {
+ MiniportBlock->LockAcquired =
+ LockAcquired = TRUE;
+
+ AdapterCB->Flags |= MINIPORT_LOCK_OWNER;
+
+ AdapterCB->SavedIrql = SavedIrql;
+ AdapterCB->MiniportLockIrql = MiniportLockIrql;
+
+ original = InterlockedExchange(&MiniportBlock->MiniportThread, CURRENT_THREAD);
+ ASSERT((LONG)NULL == original);
+
+ } else {
+ ExReleaseSpinLock(&MiniportBlock->Lock.SpinLock, MiniportLockIrql);
+ KeLowerIrql(SavedIrql);
+ }
+
+ return (LockAcquired);
+}
+
+VOID
+NdisWanReleaseMiniportLock(
+ PADAPTERCB AdapterCB
+ )
+/*++
+
+Routine Name:
+
+ NdisWanReleaseMiniportLock
+
+Routine Description:
+
+ This routine does the work that the ndis wrapper would normally do
+ to free a miniport's spinlock and local lock.
+
+Arguments:
+
+ PADAPTERCB AdapterCB -
+
+Return Values:
+
+--*/
+{
+ PNDIS_MINIPORT_BLOCK MiniportBlock;
+ KIRQL SavedIrql, MiniportLockIrql;
+
+ MiniportBlock = (PNDIS_MINIPORT_BLOCK)AdapterCB->hMiniportHandle;
+
+ NDISM_PROCESS_DEFERRED(MiniportBlock);
+
+ MiniportBlock->LockAcquired = FALSE;
+
+ ASSERT(AdapterCB->Flags & MINIPORT_LOCK_OWNER);
+
+ AdapterCB->Flags &= ~MINIPORT_LOCK_OWNER;
+
+ InterlockedExchange(&MiniportBlock->MiniportThread, 0);
+
+ SavedIrql = AdapterCB->SavedIrql;
+ MiniportLockIrql = AdapterCB->MiniportLockIrql;
+
+ ExReleaseSpinLock(&MiniportBlock->Lock.SpinLock, MiniportLockIrql);
+
+ KeLowerIrql(SavedIrql);
+}
+
+#endif // end of !USE_NDIS_MINIPORT_LOCKING
+
+#endif
+
diff --git a/private/ntos/ndis/ndiswan/vjslip.c b/private/ntos/ndis/ndiswan/vjslip.c
new file mode 100644
index 000000000..6e2288200
--- /dev/null
+++ b/private/ntos/ndis/ndiswan/vjslip.c
@@ -0,0 +1,885 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ vjslip.c
+
+Abstract:
+
+Author:
+
+ Thomas J. Dimitri (TommyD)
+
+Environment:
+
+Revision History:
+
+--*/
+#include "wan.h"
+#include "tcpip.h"
+#include "vjslip.h"
+
+#define INCR(counter) ++comp->counter;
+
+// A.2 Compression
+//
+// This routine looks daunting but isn't really. The code splits into four
+// approximately equal sized sections: The first quarter manages a
+// circularly linked, least-recently-used list of `active' TCP
+// connections./47/ The second figures out the sequence/ack/window/urg
+// changes and builds the bulk of the compressed packet. The third handles
+// the special-case encodings. The last quarter does packet ID and
+// connection ID encoding and replaces the original packet header with the
+// compressed header.
+//
+// The arguments to this routine are a pointer to a packet to be
+// compressed, a pointer to the compression state data for the serial line,
+// and a flag which enables or disables connection id (C bit) compression.
+//
+// Compression is done `in-place' so, if a compressed packet is created,
+// both the start address and length of the incoming packet (the off and
+// len fields of m) will be updated to reflect the removal of the original
+// header and its replacement by the compressed header. If either a
+// compressed or uncompressed packet is created, the compression state is
+// updated. This routines returns the packet type for the transmit framer
+// (TYPE_IP, TYPE_UNCOMPRESSED_TCP or TYPE_COMPRESSED_TCP).
+//
+// Because 16 and 32 bit arithmetic is done on various header fields, the
+// incoming IP packet must be aligned appropriately (e.g., on a SPARC, the
+// IP header is aligned on a 32-bit boundary). Substantial changes would
+// have to be made to the code below if this were not true (and it would
+// probably be cheaper to byte copy the incoming header to somewhere
+// correctly aligned than to make those changes).
+//
+// Note that the outgoing packet will be aligned arbitrarily (e.g., it
+// could easily start on an odd-byte boundary).
+//
+
+UCHAR
+sl_compress_tcp(
+ PUUCHAR UNALIGNED *m_off, // Frame start (points to IP header)
+ ULONG *m_len, // Length of entire frame
+ struct slcompress *comp, // Compression struct for this link
+ ULONG compress_cid) { // Compress connection id boolean
+
+ struct cstate *cs = comp->last_cs->cs_next;
+ struct ip UNALIGNED *ip = (struct ip UNALIGNED *)*m_off;
+ ULONG hlen = ip->ip_hl & 0x0F; // last 4 bits are the length
+ struct tcphdr UNALIGNED *oth; /* last TCP header */
+ struct tcphdr UNALIGNED *th; /* current TCP header */
+
+// ----------------------------
+// 47. The two most common operations on the connection list are a `find'
+// that terminates at the first entry (a new packet for the most recently
+// used connection) and moving the last entry on the list to the head of
+// the list (the first packet from a new connection). A circular list
+// efficiently handles these two operations.
+
+ ULONG deltaS, deltaA; /* general purpose temporaries */
+ ULONG changes = 0; /* change mask */
+ UCHAR new_seq[16]; /* changes from last to current */
+ UCHAR UNALIGNED *cp = new_seq;
+ USHORT ip_len;
+
+ /*
+ * Bail if this is an IP fragment or if the TCP packet isn't
+ * `compressible' (i.e., ACK isn't set or some other control bit is
+ * set). Or if it does not contain the TCP protocol.
+ */
+ if ((ip->ip_off & 0xff3f) || *m_len < 40 || ip->ip_p != IPPROTO_TCP)
+ return (TYPE_IP);
+
+ th = (struct tcphdr UNALIGNED *) & ((PULONG) ip)[hlen];
+ if ((th->th_flags & (TH_SYN | TH_FIN | TH_RST | TH_ACK)) != TH_ACK)
+ return (TYPE_IP);
+
+ /*
+ * Packet is compressible -- we're going to send either a
+ * COMPRESSED_TCP or UNCOMPRESSED_TCP packet. Either way we need to
+ * locate (or create) the connection state. Special case the most
+ * recently used connection since it's most likely to be used again &
+ * we don't have to do any reordering if it's used.
+ */
+
+ //
+ // Keep stats here
+ //
+ INCR(OutPackets);
+
+ if (ip->ip_src.s_addr != cs->cs_ip.ip_src.s_addr ||
+ ip->ip_dst.s_addr != cs->cs_ip.ip_dst.s_addr ||
+ *(ULONG UNALIGNED *) th != ((ULONG UNALIGNED *) &cs->cs_ip)[cs->cs_ip.ip_hl & 0x0F]) {
+
+ /*
+ * Wasn't the first -- search for it.
+ *
+ * States are kept in a circularly linked list with last_cs
+ * pointing to the end of the list. The list is kept in lru
+ * order by moving a state to the head of the list whenever
+ * it is referenced. Since the list is short and,
+ * empirically, the connection we want is almost always near
+ * the front, we locate states via linear search. If we
+ * don't find a state for the datagram, the oldest state is
+ * (re-)used.
+ */
+ struct cstate *lcs;
+ struct cstate *lastcs = comp->last_cs;
+
+ do {
+ lcs = cs;
+ cs = cs->cs_next;
+ INCR(OutSearches);
+
+ if (ip->ip_src.s_addr == cs->cs_ip.ip_src.s_addr &&
+ ip->ip_dst.s_addr == cs->cs_ip.ip_dst.s_addr &&
+ *(ULONG UNALIGNED *) th == ((ULONG UNALIGNED *) &cs->cs_ip)[cs->cs_ip.ip_hl & 0x0F])
+
+ goto found;
+
+ } while (cs != lastcs);
+
+ /*
+ * Didn't find it -- re-use oldest cstate. Send an
+ * uncompressed packet that tells the other side what
+ * connection number we're using for this conversation. Note
+ * that since the state list is circular, the oldest state
+ * points to the newest and we only need to set last_cs to
+ * update the lru linkage.
+ */
+
+ INCR(OutMisses);
+
+ //
+ // A miss!
+ //
+ comp->last_cs = lcs;
+ hlen += (th->th_off >> 4);
+ hlen <<= 2;
+
+ if (hlen > *m_len) {
+ return(TYPE_IP);
+ }
+
+ goto uncompressed;
+
+found:
+ /* Found it -- move to the front on the connection list. */
+ if (cs == lastcs)
+ comp->last_cs = lcs;
+ else {
+ lcs->cs_next = cs->cs_next;
+ cs->cs_next = lastcs->cs_next;
+ lastcs->cs_next = cs;
+ }
+ }
+
+ /*
+ * Make sure that only what we expect to change changed. The first
+ * line of the `if' checks the IP protocol version, header length &
+ * type of service. The 2nd line checks the "Don't fragment" bit.
+ * The 3rd line checks the time-to-live and protocol (the protocol
+ * check is unnecessary but costless). The 4th line checks the TCP
+ * header length. The 5th line checks IP options, if any. The 6th
+ * line checks TCP options, if any. If any of these things are
+ * different between the previous & current datagram, we send the
+ * current datagram `uncompressed'.
+ */
+ oth = (struct tcphdr UNALIGNED *) & ((ULONG UNALIGNED *) &cs->cs_ip)[hlen];
+ deltaS = hlen;
+ hlen += (th->th_off >> 4);
+ hlen <<= 2;
+
+ //
+ // Bug fix? It's in cslip.tar.Z
+ //
+ if (hlen > *m_len) {
+ NdisWanDbgOut(DBG_FAILURE, DBG_VJ,("Bad TCP packet length\n"));
+ return(TYPE_IP);
+ }
+
+ if (((PUSHORT) ip)[0] != ((PUSHORT) &cs->cs_ip)[0] ||
+ ((PUSHORT) ip)[3] != ((PUSHORT) &cs->cs_ip)[3] ||
+ ((PUSHORT) ip)[4] != ((PUSHORT) &cs->cs_ip)[4] ||
+ (th->th_off >> 4) != (oth->th_off >> 4) ||
+ (deltaS > 5 &&
+ memcmp((PUCHAR)(ip + 1), (PUCHAR)(&cs->cs_ip + 1), (deltaS - 5) << 2)) ||
+ ((th->th_off >> 4) > 5 &&
+ memcmp((PUCHAR)(th + 1), (PUCHAR)(oth + 1), ((th->th_off >> 4) - 5) << 2))) {
+
+ goto uncompressed;
+ }
+
+ /*
+ * Figure out which of the changing fields changed. The receiver
+ * expects changes in the order: urgent, window, ack, seq.
+ */
+ if (th->th_flags & TH_URG) {
+ deltaS = ntohs(th->th_urp);
+ ENCODEZ(deltaS);
+ changes |= NEW_U;
+ } else if (th->th_urp != oth->th_urp) {
+
+ /*
+ * argh! URG not set but urp changed -- a sensible
+ * implementation should never do this but RFC793 doesn't
+ * prohibit the change so we have to deal with it.
+ */
+ goto uncompressed;
+ }
+
+ if (deltaS = (USHORT) (ntohs(th->th_win) - ntohs(oth->th_win))) {
+ ENCODE(deltaS);
+ changes |= NEW_W;
+ }
+ if (deltaA = ntohl(th->th_ack) - ntohl(oth->th_ack)) {
+ if (deltaA > 0xffff) {
+ goto uncompressed;
+ }
+
+ ENCODE(deltaA);
+ changes |= NEW_A;
+ }
+ if (deltaS = ntohl(th->th_seq) - ntohl(oth->th_seq)) {
+ if (deltaS > 0xffff) {
+ goto uncompressed;
+ }
+
+ ENCODE(deltaS);
+ changes |= NEW_S;
+ }
+
+ ip_len = ntohs(cs->cs_ip.ip_len);
+
+ /*
+ * Look for the special-case encodings.
+ */
+ switch (changes) {
+
+ case 0:
+ /*
+ * Nothing changed. If this packet contains data and the last
+ * one didn't, this is probably a data packet following an
+ * ack (normal on an interactive connection) and we send it
+ * compressed. Otherwise it's probably a retransmit,
+ * retransmitted ack or window probe. Send it uncompressed
+ * in case the other side missed the compressed version.
+ */
+ if (ip->ip_len != cs->cs_ip.ip_len &&
+ ip_len == hlen)
+
+ break;
+
+ /* (fall through) */
+
+ case SPECIAL_I:
+ case SPECIAL_D:
+ /*
+ * Actual changes match one of our special case encodings --
+ * send packet uncompressed.
+ */
+ goto uncompressed;
+
+ case NEW_S | NEW_A:
+ if (deltaS == deltaA &&
+ deltaS == ip_len - hlen) {
+ /* special case for echoed terminal traffic */
+ changes = SPECIAL_I;
+ cp = new_seq;
+ }
+ break;
+
+ case NEW_S:
+ if (deltaS == ip_len - hlen) {
+ /* special case for data xfer */
+ changes = SPECIAL_D;
+ cp = new_seq;
+ }
+ break;
+ }
+
+ deltaS = ntohs(ip->ip_id) - ntohs(cs->cs_ip.ip_id);
+
+ if (deltaS != 1) {
+ ENCODEZ(deltaS);
+ changes |= NEW_I;
+ }
+
+ if (th->th_flags & TH_PUSH)
+ changes |= TCP_PUSH_BIT;
+ /*
+ * Grab the cksum before we overwrite it below. Then update our
+ * state with this packet's header.
+ */
+ deltaA = (th->th_sumhi << 8) + th->th_sumlo;
+
+ NdisMoveMemory((PUCHAR)&cs->cs_ip,
+ (PUCHAR)ip,
+ hlen);
+
+ /*
+ * We want to use the original packet as our compressed packet. (cp -
+ * new_seq) is the number of bytes we need for compressed sequence
+ * numbers. In addition we need one byte for the change mask, one
+ * for the connection id and two for the tcp checksum. So, (cp -
+ * new_seq) + 4 bytes of header are needed. hlen is how many bytes
+ * of the original packet to toss so subtract the two to get the new
+ * packet size.
+ */
+ deltaS = cp - new_seq;
+ cp = (UCHAR UNALIGNED *) ip;
+
+ if (compress_cid == 0 || comp->last_xmit != cs->cs_id) {
+ comp->last_xmit = cs->cs_id;
+ hlen -= deltaS + 4;
+ cp += hlen;
+ *cp++ = (UCHAR)(changes | NEW_C);
+ *cp++ = cs->cs_id;
+ } else {
+ hlen -= deltaS + 3;
+ cp += hlen;
+ *cp++ = (UCHAR)changes;
+ }
+
+ *m_len -= hlen;
+ *m_off += hlen;
+ *cp++ = (UCHAR)(deltaA >> 8);
+ *cp++ = (UCHAR)(deltaA);
+
+ NdisMoveMemory((PUCHAR)cp,
+ (PUCHAR)new_seq,
+ deltaS);
+
+ INCR(OutCompressed);
+ return (TYPE_COMPRESSED_TCP);
+
+uncompressed:
+ /*
+ * Update connection state cs & send uncompressed packet
+ * ('uncompressed' means a regular ip/tcp packet but with the
+ * 'conversation id' we hope to use on future compressed packets in
+ * the protocol field).
+ */
+
+ NdisMoveMemory((PUCHAR)&cs->cs_ip,
+ (PUCHAR)ip,
+ hlen);
+
+ ip->ip_p = cs->cs_id;
+ comp->last_xmit = cs->cs_id;
+ return (TYPE_UNCOMPRESSED_TCP);
+}
+
+
+
+
+
+// A.3 Decompression
+//
+// This routine decompresses a received packet. It is called with a
+// pointer to the packet, the packet length and type, and a pointer to the
+// compression state structure for the incoming serial line. It returns a
+// pointer to the resulting packet or zero if there were errors in the
+// incoming packet. If the packet is COMPRESSED_TCP or UNCOMPRESSED_TCP,
+// the compression state will be updated.
+//
+// The new packet will be constructed in-place. That means that there must
+// be 128 bytes of free space in front of bufp to allow room for the
+// reconstructed IP and TCP headers. The reconstructed packet will be
+// aligned on a 32-bit boundary.
+//
+
+//LONG
+//sl_uncompress_tcp(
+// PUUCHAR UNALIGNED *bufp,
+// LONG len,
+// UCHAR type,
+// struct slcompress *comp) {
+LONG
+sl_uncompress_tcp(
+ PUUCHAR UNALIGNED *InBuffer,
+ PULONG InLength,
+ UCHAR UNALIGNED *OutBuffer,
+ PULONG OutLength,
+ UCHAR type,
+ struct slcompress *comp
+ )
+{
+ UCHAR UNALIGNED *cp;
+ ULONG inlen;
+ ULONG hlen, changes;
+ struct tcphdr UNALIGNED *th;
+ struct cstate *cs;
+ struct ip UNALIGNED *ip;
+
+ inlen = *InLength;
+
+ switch (type) {
+
+ case TYPE_ERROR:
+ default:
+ NdisWanDbgOut(DBG_FAILURE, DBG_VJ, ("Packet transmission error type 0x%.2x\n",type));
+ goto bad;
+
+ case TYPE_IP:
+ break;
+
+ case TYPE_UNCOMPRESSED_TCP:
+ /*
+ * Locate the saved state for this connection. If the state
+ * index is legal, clear the 'discard' flag.
+ */
+ ip = (struct ip UNALIGNED *) *InBuffer;
+ if (ip->ip_p >= comp->MaxStates) {
+ NdisWanDbgOut(DBG_FAILURE, DBG_VJ, ("Max state exceeded %u\n", ip->ip_p));
+ goto bad;
+ }
+
+ cs = &comp->rstate[comp->last_recv = ip->ip_p];
+ comp->flags &= ~SLF_TOSS;
+
+ /*
+ * Restore the IP protocol field then save a copy of this
+ * packet header. (The checksum is zeroed in the copy so we
+ * don't have to zero it each time we process a compressed
+ * packet.
+ */
+ hlen = ip->ip_hl & 0x0F;
+ hlen += ((struct tcphdr UNALIGNED *) & ((ULONG UNALIGNED *) ip)[hlen])->th_off >> 4;
+ hlen <<= 2;
+
+ NdisMoveMemory((PUCHAR)&cs->cs_ip,
+ (PUCHAR)ip,
+ hlen);
+
+ cs->cs_ip.ip_p = IPPROTO_TCP;
+
+ NdisMoveMemory((PUCHAR)OutBuffer,
+ (PUCHAR)&cs->cs_ip,
+ hlen);
+
+ cs->cs_ip.ip_sum = 0;
+ cs->cs_hlen = (USHORT)hlen;
+
+ *InBuffer = (PUCHAR)ip + hlen;
+ *InLength = inlen - hlen;
+ *OutLength = hlen;
+
+ INCR(InUncompressed);
+ return (inlen);
+
+ case TYPE_COMPRESSED_TCP:
+ break;
+ }
+
+ /* We've got a compressed packet. */
+ INCR(InCompressed);
+ cp = *InBuffer;
+ changes = *cp++;
+
+ if (changes & NEW_C) {
+ /*
+ * Make sure the state index is in range, then grab the
+ * state. If we have a good state index, clear the 'discard'
+ * flag.
+ */
+ if (*cp >= comp->MaxStates) {
+ NdisWanDbgOut(DBG_FAILURE, DBG_VJ, ("MaxState of %u too big\n", *cp));
+ goto bad;
+ }
+
+ comp->flags &= ~SLF_TOSS;
+ comp->last_recv = *cp++;
+ } else {
+ /*
+ * This packet has an implicit state index. If we've had a
+ * line error since the last time we got an explicit state
+ * index, we have to toss the packet.
+ */
+ if (comp->flags & SLF_TOSS) {
+ NdisWanDbgOut(DBG_FAILURE, DBG_VJ,("Packet has state index, have to toss it\n"));
+ INCR(InTossed);
+ return (0);
+ }
+ }
+
+ /*
+ * Find the state then fill in the TCP checksum and PUSH bit.
+ */
+
+ cs = &comp->rstate[comp->last_recv];
+ hlen = (cs->cs_ip.ip_hl & 0x0F) << 2;
+ th = (struct tcphdr UNALIGNED *) & ((UCHAR UNALIGNED *) &cs->cs_ip)[hlen];
+
+ th->th_sumhi = cp[0];
+ th->th_sumlo = cp[1];
+
+ cp += 2;
+ if (changes & TCP_PUSH_BIT)
+ th->th_flags |= TH_PUSH;
+ else
+ th->th_flags &= ~TH_PUSH;
+
+ /*
+ * Fix up the state's ack, seq, urg and win fields based on the
+ * changemask.
+ */
+ switch (changes & SPECIALS_MASK) {
+ case SPECIAL_I:
+ {
+ UCHAR UNALIGNED * piplen=(UCHAR UNALIGNED *)&(cs->cs_ip.ip_len);
+ UCHAR UNALIGNED * ptcplen;
+ ULONG tcplen;
+ ULONG i;
+
+ i = ((piplen[0] << 8) + piplen[1]) - cs->cs_hlen;
+
+// th->th_ack = htonl(ntohl(th->th_ack) + i);
+
+ ptcplen=(UCHAR UNALIGNED *)&(th->th_ack);
+ tcplen=(ptcplen[0] << 24) + (ptcplen[1] << 16) +
+ (ptcplen[2] << 8) + ptcplen[3] + i;
+ ptcplen[3]=(UCHAR)(tcplen);
+ ptcplen[2]=(UCHAR)(tcplen >> 8);
+ ptcplen[1]=(UCHAR)(tcplen >> 16);
+ ptcplen[0]=(UCHAR)(tcplen >> 24);
+
+
+// th->th_seq = htonl(ntohl(th->th_seq) + i);
+
+ ptcplen=(UCHAR UNALIGNED *)&(th->th_seq);
+ tcplen=(ptcplen[0] << 24) + (ptcplen[1] << 16) +
+ (ptcplen[2] << 8) + ptcplen[3] + i;
+ ptcplen[3]=(UCHAR)(tcplen);
+ ptcplen[2]=(UCHAR)(tcplen >> 8);
+ ptcplen[1]=(UCHAR)(tcplen >> 16);
+ ptcplen[0]=(UCHAR)(tcplen >> 24);
+
+ }
+ break;
+
+ case SPECIAL_D:
+ {
+// th->th_seq = htonl(ntohl(th->th_seq) + ntohs(cs->cs_ip.ip_len)
+// - cs->cs_hlen);
+
+ UCHAR UNALIGNED *piplen=(UCHAR UNALIGNED *)&(cs->cs_ip.ip_len);
+ UCHAR UNALIGNED *ptcplen;
+ ULONG tcplen;
+ ULONG i;
+
+ i = ((piplen[0] << 8) + piplen[1]) - cs->cs_hlen;
+
+ ptcplen=(UCHAR UNALIGNED *)&(th->th_seq);
+ tcplen=(ptcplen[0] << 24) + (ptcplen[1] << 16) +
+ (ptcplen[2] << 8) + ptcplen[3] + i;
+
+ ptcplen[3]=(UCHAR)(tcplen);
+ ptcplen[2]=(UCHAR)(tcplen >> 8);
+ ptcplen[1]=(UCHAR)(tcplen >> 16);
+ ptcplen[0]=(UCHAR)(tcplen >> 24);
+
+
+ }
+
+ break;
+
+ default:
+ if (changes & NEW_U) {
+ th->th_flags |= TH_URG;
+ DECODEU(th->th_urp)
+ } else
+ th->th_flags &= ~TH_URG;
+
+ if (changes & NEW_W)
+ DECODES(th->th_win);
+ if (changes & NEW_A)
+ DECODEL(th->th_ack)
+ if (changes & NEW_S)
+ DECODEL(th->th_seq)
+
+ break;
+ }
+ /* Update the IP ID */
+ if (changes & NEW_I) {
+
+ DECODES(cs->cs_ip.ip_id)
+
+ } else {
+
+ USHORT id;
+ UCHAR UNALIGNED *pid = (UCHAR UNALIGNED *)&(cs->cs_ip.ip_id);
+
+// cs->cs_ip.ip_id = htons(ntohs(cs->cs_ip.ip_id) + 1);
+ id=(pid[0] << 8) + pid[1] + 1;
+ pid[0]=(UCHAR)(id >> 8);
+ pid[1]=(UCHAR)(id);
+ }
+
+
+ /*
+ * At this point, cp points to the first byte of data in the packet.
+ * If we're not aligned on a 4-byte boundary, copy the data down so
+ * the IP & TCP headers will be aligned. Then back up cp by the
+ * TCP/IP header length to make room for the reconstructed header (we
+ * assume the packet we were handed has enough space to prepend 128
+ * bytes of header). Adjust the lenth to account for the new header
+ * & fill in the IP total length.
+ */
+// len -= (cp - *bufp);
+ inlen -= (cp - *InBuffer);
+
+ if (inlen < 0) {
+
+ /*
+ * we must have dropped some characters (crc should detect
+ * this but the old slip framing won't)
+ */
+ NdisWanDbgOut(DBG_FAILURE, DBG_VJ,("len has dropped below 0!\n"));
+ goto bad;
+ }
+//
+// SCREW 4 byte alignement! It's just a useless big copy!
+//
+// if ((ULONG) cp & 3) {
+// if (len > 0)
+// //
+// // BUG BUG we want OVBCOPY..
+// //
+// NdisMoveMemory(
+// (PUCHAR)((ULONG) cp & ~3),
+// cp,
+// len);
+// cp = (PUCHAR) ((ULONG) cp & ~3);
+// }
+
+// cp -= cs->cs_hlen;
+// len += cs->cs_hlen;
+
+// cs->cs_ip.ip_len = htons(len);
+ cs->cs_ip.ip_len = htons(inlen + cs->cs_hlen);
+
+// NdisMoveMemory(
+// (PUCHAR)cp,
+// (PUCHAR)&cs->cs_ip,
+// cs->cs_hlen);
+
+ NdisMoveMemory((PUCHAR)OutBuffer,
+ (PUCHAR)&cs->cs_ip,
+ cs->cs_hlen);
+
+// *bufp = cp;
+ *InBuffer = cp;
+ *InLength = inlen;
+ *OutLength = cs->cs_hlen;
+
+ /* recompute the ip header checksum */
+ {
+// USHORT UNALIGNED * bp = (USHORT UNALIGNED *) cp;
+ USHORT UNALIGNED * bp = (USHORT UNALIGNED *) OutBuffer;
+
+ for (changes = 0; hlen > 0; hlen -= 2)
+ changes += *bp++;
+
+ changes = (changes & 0xffff) + (changes >> 16);
+ changes = (changes & 0xffff) + (changes >> 16);
+// ((struct ip UNALIGNED *) cp)->ip_sum = (USHORT)~changes;
+ ((struct ip UNALIGNED *) OutBuffer)->ip_sum = (USHORT)~changes;
+ }
+
+ return (inlen + cs->cs_hlen);
+
+bad:
+ comp->flags |= SLF_TOSS;
+ INCR(InErrors);
+ return (0);
+}
+
+
+
+
+// A.4 Initialization
+//
+// This routine initializes the state structure for both the transmit and
+// receive halves of some serial line. It must be called each time the
+// line is brought up.
+//
+
+NDIS_STATUS
+sl_compress_init(
+ struct slcompress **retcomp,
+ UCHAR MaxStates
+ )
+{
+ ULONG i;
+ struct cstate *tstate; // = comp->tstate;
+ struct slcompress *comp;
+
+ comp = *retcomp;
+
+ //
+ // Do we need to allocate memory for this bundle
+ //
+
+ if (comp != NULL) {
+ return (NDIS_STATUS_SUCCESS);
+ }
+
+
+ NdisWanAllocateMemory(&comp, sizeof(slcompress));
+
+ //
+ // If there was no memory to allocate
+ //
+ if (comp == NULL) {
+
+ return(NDIS_STATUS_RESOURCES);
+ }
+
+ tstate = comp->tstate;
+
+ /*
+ * Clean out any junk left from the last time line was used.
+ */
+ NdisZeroMemory(
+ (PUCHAR) comp,
+ sizeof(*comp));
+
+ /*
+ * Link the transmit states into a circular list.
+ */
+ for (i = MaxStates - 1; i > 0; --i) {
+ tstate[i].cs_id = (UCHAR)i;
+ tstate[i].cs_next = &tstate[i - 1];
+ }
+
+ tstate[0].cs_next = &tstate[MaxStates - 1];
+ tstate[0].cs_id = 0;
+ comp->last_cs = &tstate[0];
+
+ /*
+ * Make sure we don't accidentally do CID compression
+ * (assumes MAX_VJ_STATES < 255).
+ */
+ comp->last_recv = 255;
+ comp->last_xmit = 255;
+ comp->flags = SLF_TOSS;
+ comp->MaxStates=MaxStates;
+
+ *retcomp = comp;
+
+ return (NDIS_STATUS_SUCCESS);
+}
+
+VOID
+sl_compress_terminate(
+ struct slcompress **comp
+ )
+{
+ if (*comp != NULL) {
+ NdisWanFreeMemory(*comp);
+ *comp = NULL;
+ }
+}
+
+// A.5 Berkeley Unix dependencies
+//
+// Note: The following is of interest only if you are trying to bring the
+// sample code up on a system that is not derived from 4BSD (Berkeley
+// Unix).
+//
+// The code uses the normal Berkeley Unix header files (from
+// /usr/include/netinet) for definitions of the structure of IP and TCP
+// headers. The structure tags tend to follow the protocol RFCs closely
+// and should be obvious even if you do not have access to a 4BSD
+// system./48/
+//
+// ----------------------------
+// 48. In the event they are not obvious, the header files (and all the
+// Berkeley networking code) can be anonymous ftp'd from host
+//
+//
+// The macro BCOPY(src, dst, amt) is invoked to copy amt bytes from src to
+// dst. In BSD, it translates into a call to BCOPY. If you have the
+// misfortune to be running System-V Unix, it can be translated into a call
+// to memcpy. The macro OVBCOPY(src, dst, amt) is used to copy when src
+// and dst overlap (i.e., when doing the 4-byte alignment copy). In the
+// BSD kernel, it translates into a call to ovbcopy. Since AT&T botched
+// the definition of memcpy, this should probably translate into a copy
+// loop under System-V.
+//
+// The macro BCMP(src, dst, amt) is invoked to compare amt bytes of src and
+// dst for equality. In BSD, it translates into a call to bcmp. In
+// System-V, it can be translated into a call to memcmp or you can write a
+// routine to do the compare. The routine should return zero if all bytes
+// of src and dst are equal and non-zero otherwise.
+//
+// The routine ntohl(dat) converts (4 byte) long dat from network byte
+// order to host byte order. On a reasonable cpu this can be the no-op
+// macro:
+// #define ntohl(dat) (dat)
+//
+// On a Vax or IBM PC (or anything with Intel byte order), you will have to
+// define a macro or routine to rearrange bytes.
+//
+// The routine ntohs(dat) is like ntohl but converts (2 byte) shorts
+// instead of longs. The routines htonl(dat) and htons(dat) do the inverse
+// transform (host to network byte order) for longs and shorts.
+//
+// A struct mbuf is used in the call to sl_compress_tcp because that
+// routine needs to modify both the start address and length if the
+// incoming packet is compressed. In BSD, an mbuf is the kernel's buffer
+// management structure. If other systems, the following definition should
+// be sufficient:
+//
+// struct mbuf {
+// UCHAR *m_off; /* pointer to start of data */
+// int m_len; /* length of data */
+// };
+//
+// #define mtod(m, t) ((t)(m->m_off))
+//
+//
+// B Compatibility with past mistakes
+//
+//
+// When combined with the modern PPP serial line protocol[9], the use of
+// header compression is automatic and invisible to the user.
+// Unfortunately, many sites have existing users of the SLIP described in
+// [12] which doesn't allow for different protocol types to distinguish
+// header compressed packets from IP packets or for version numbers or an
+// option exchange that could be used to automatically negotiate header
+// compression.
+//
+// The author has used the following tricks to allow header compressed SLIP
+// to interoperate with the existing servers and clients. Note that these
+// are hacks for compatibility with past mistakes and should be offensive
+// to any right thinking person. They are offered solely to ease the pain
+// of running SLIP while users wait patiently for vendors to release PPP.
+//
+//
+// B.1 Living without a framing `type' byte
+//
+// The bizarre packet type numbers in sec. A.1 were chosen to allow a
+// `packet type' to be sent on lines where it is undesirable or impossible
+// to add an explicit type byte. Note that the first byte of an IP packet
+// always contains `4' (the IP protocol version) in the top four bits. And
+// that the most significant bit of the first byte of the compressed header
+// is ignored. Using the packet types in sec. A.1, the type can be encoded
+// in the most significant bits of the outgoing packet using the code
+//
+// p->dat[0] |= sl_compress_tcp(p, comp);
+//
+// and decoded on the receive side by
+//
+// if (p->dat[0] & 0x80)
+// type = TYPE_COMPRESSED_TCP;
+// else if (p->dat[0] >= 0x70) {
+// type = TYPE_UNCOMPRESSED_TCP;
+// p->dat[0] &=~ 0x30;
+// } else
+// type = TYPE_IP;
+// status = sl_uncompress_tcp(p, type, comp);
+
+
diff --git a/private/ntos/ndis/ndiswan/vjslip.h b/private/ntos/ndis/ndiswan/vjslip.h
new file mode 100644
index 000000000..e171125ea
--- /dev/null
+++ b/private/ntos/ndis/ndiswan/vjslip.h
@@ -0,0 +1,249 @@
+#ifndef _VJSLIP_
+#define _VJSLIP_
+
+/*
+ * Copyright (c) 1989 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are
+ * permitted provided that the above copyright notice and this
+ * paragraph are duplicated in all such forms and that any
+ * documentation, advertising materials, and other materials
+ * related to such distribution and use acknowledge that the
+ * software was developed by the University of California,
+ * Berkeley. The name of the University may not be used to
+ * endorse or promote products derived from this software
+ * without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE
+ * IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE.
+ */
+
+
+// A.1 Definitions and State Data
+
+#define MAX_VJ_STATES 16 /* must be >2 and <255 */
+#define MAX_HDR 128 /* max TCP+IP hdr length (by protocol def) */
+
+
+//
+// NT is little endian, so we follow these rules
+//
+#define ntohs(x) (USHORT)( ((x) >> 8) + (((x) & 0xFF) << 8) )
+
+#define ntohl(x) (ULONG) ( ((x) >> 24) + (((x) & 0xFF0000) >> 8) +\
+ (((x) & 0xFF00) << 8) + (((x) & 0xFF) << 24) )
+
+#define htons(x) ntohs(x)
+#define htonl(x) ntohl(x)
+
+
+/* packet types */
+#define TYPE_IP 0x40
+#define TYPE_UNCOMPRESSED_TCP 0x70
+#define TYPE_COMPRESSED_TCP 0x80
+#define TYPE_ERROR 0x00
+ /* this is not a type that ever appears on
+ * the wire. The receive framer uses it to
+ * tell the decompressor there was a packet
+ * transmission error. */
+/*
+ * Bits in first octet of compressed packet
+ */
+
+/* flag bits for what changed in a packet */
+
+#define NEW_C 0x40
+#define NEW_I 0x20
+#define TCP_PUSH_BIT 0x10
+
+#define NEW_S 0x08
+#define NEW_A 0x04
+#define NEW_W 0x02
+#define NEW_U 0x01
+
+
+/* reserved, special-case values of above */
+#define SPECIAL_I (NEW_S|NEW_W|NEW_U) /* echoed interactive traffic */
+#define SPECIAL_D (NEW_S|NEW_A|NEW_W|NEW_U) /* unidirectional data */
+#define SPECIALS_MASK (NEW_S|NEW_A|NEW_W|NEW_U)
+
+
+/*
+ * "state" data for each active tcp conversation on the wire. This is
+ * basically a copy of the entire IP/TCP header from the last packet together
+ * with a small identifier the transmit & receive ends of the line use to
+ * locate saved header.
+ */
+
+struct cstate {
+ struct cstate *cs_next; /* next most recently used cstate (xmit only) */
+ USHORT cs_hlen; /* size of hdr (receive only) */
+ UCHAR cs_id; /* connection # associated with this state */
+ UCHAR cs_filler;
+ union {
+ UCHAR hdr[MAX_HDR];
+ struct ip UNALIGNED csu_ip; /* ip/tcp hdr from most recent packet */
+ } slcs_u;
+};
+
+#define cs_ip slcs_u.csu_ip
+
+#define cs_hdr slcs_u.csu_hdr
+
+/*
+ * all the state data for one serial line (we need one of these per line).
+ */
+typedef struct slcompress slcompress;
+
+struct slcompress {
+ struct cstate *last_cs; /* most recently used tstate */
+ UCHAR last_recv; /* last rcvd conn. id */
+ UCHAR last_xmit; /* last sent conn. id */
+ USHORT flags;
+ UCHAR MaxStates;
+//
+// Some Statistics
+//
+ ULONG OutPackets;
+ ULONG OutCompressed;
+ ULONG OutSearches;
+ ULONG OutMisses;
+ ULONG InUncompressed;
+ ULONG InCompressed;
+ ULONG InErrors;
+ ULONG InTossed;
+
+ struct cstate tstate[MAX_VJ_STATES]; /* xmit connection states */
+ struct cstate rstate[MAX_VJ_STATES]; /* receive connection states */
+};
+
+struct mbuf {
+ PUCHAR m_off; // pointer to start of data
+ UINT m_len; // length of data
+};
+
+#define mtod(m,t) ((t)(m->m_off))
+
+/* flag values */
+#define SLF_TOSS 1 /* tossing rcvd frames because of input err */
+
+/*
+ * The following macros are used to encode and decode numbers. They all
+ * assume that `cp' points to a buffer where the next byte encoded (decoded)
+ * is to be stored (retrieved). Since the decode routines do arithmetic,
+ * they have to convert from and to network byte order.
+ */
+
+/*
+ * ENCODE encodes a number that is known to be non-zero. ENCODEZ checks for
+ * zero (zero has to be encoded in the long, 3 byte form).
+ */
+#define ENCODE(n) { \
+ if ((USHORT)(n) >= 256) { \
+ *cp++ = 0; \
+ cp[1] = (UCHAR)(n); \
+ cp[0] = (UCHAR)((n) >> 8); \
+ cp += 2; \
+ } else { \
+ *cp++ = (UCHAR)(n); \
+ } \
+}
+
+#define ENCODEZ(n) { \
+ if ((USHORT)(n) >= 256 || (USHORT)(n) == 0) { \
+ *cp++ = 0; \
+ cp[1] = (UCHAR)(n); \
+ cp[0] = (UCHAR)((n) >> 8); \
+ cp += 2; \
+ } else { \
+ *cp++ = (UCHAR)(n); \
+ } \
+}
+
+/*
+ * DECODEL takes the (compressed) change at byte cp and adds it to the
+ * current value of packet field 'f' (which must be a 4-byte (long) integer
+ * in network byte order). DECODES does the same for a 2-byte (short) field.
+ * DECODEU takes the change at cp and stuffs it into the (short) field f.
+ * 'cp' is updated to point to the next field in the compressed header.
+ */
+
+#define DECODEL(f) { \
+ ULONG _x_ = ntohl(f); \
+ if (*cp == 0) {\
+ _x_ += ((cp[1] << 8) + cp[2]); \
+ (f) = htonl(_x_); \
+ cp += 3; \
+ } else { \
+ _x_ += *cp; \
+ (f) = htonl(_x_); \
+ cp++; \
+ } \
+}
+
+#define DECODES(f) { \
+ USHORT _x_= ntohs(f); \
+ if (*cp == 0) {\
+ _x_ += ((cp[1] << 8) + cp[2]); \
+ (f) = htons(_x_); \
+ cp += 3; \
+ } else { \
+ _x_ += *cp; \
+ (f) = htons(_x_); \
+ cp++; \
+ } \
+}
+
+#define DECODEU(f) { \
+ USHORT _x_; \
+ if (*cp == 0) {\
+ _x_=(cp[1] << 8) + cp[2]; \
+ (f) = htons(_x_); \
+ cp += 3; \
+ } else { \
+ _x_=*cp; \
+ (f) = htons(_x_); \
+ cp++; \
+ } \
+}
+
+typedef UCHAR UNALIGNED * PUUCHAR;
+
+
+UCHAR
+sl_compress_tcp(
+ PUUCHAR UNALIGNED *m_off, // Frame start (points to IP header)
+ PULONG m_len, // Length of entire frame
+ struct slcompress *comp, // Compression struct for this link
+ ULONG compress_cid); // Compress connection id boolean
+
+//LONG
+//sl_uncompress_tcp(
+// PUUCHAR UNALIGNED *bufp,
+// LONG len,
+// UCHAR type,
+// struct slcompress *comp);
+LONG
+sl_uncompress_tcp(
+ PUUCHAR UNALIGNED *InBuffer,
+ PULONG InLength,
+ UCHAR UNALIGNED *OutBuffer,
+ PULONG OutLength,
+ UCHAR type,
+ struct slcompress *comp
+ );
+
+NDIS_STATUS
+sl_compress_init(
+ struct slcompress **comp,
+ UCHAR MaxStates);
+
+VOID
+sl_compress_terminate(
+ struct slcompress **comp
+ );
+
+#endif // _VJSLIP_
+
diff --git a/private/ntos/ndis/ndiswan/wan.h b/private/ntos/ndis/ndiswan/wan.h
new file mode 100644
index 000000000..6137d7a18
--- /dev/null
+++ b/private/ntos/ndis/ndiswan/wan.h
@@ -0,0 +1,42 @@
+/*++
+
+Copyright (c) 1990-1995 Microsoft Corporation
+
+Module Name:
+
+ Wan.h
+
+Abstract:
+
+ This file contains all include files for the NdisWan driver.
+
+
+
+Author:
+
+ Tony Bell (TonyBe) June 06, 1995
+
+Environment:
+
+ Kernel Mode
+
+Revision History:
+
+ TonyBe 06/06/95 Created
+
+--*/
+
+#include <ndis.h>
+#include <ndiswan.h>
+#include <ndistapi.h>
+#include <efilter.h>
+#include <ntddk.h>
+#include <ndisprv.h>
+
+#include "wandefs.h"
+#include "wanpub.h"
+#include "wantypes.h"
+#include "adapter.h"
+#include "global.h"
+#include "wanproto.h"
+
diff --git a/private/ntos/ndis/ndiswan/wandefs.h b/private/ntos/ndis/ndiswan/wandefs.h
new file mode 100644
index 000000000..18fd45d7b
--- /dev/null
+++ b/private/ntos/ndis/ndiswan/wandefs.h
@@ -0,0 +1,649 @@
+/*++
+
+Copyright (c) 1990-1995 Microsoft Corporation
+
+Module Name:
+
+ Wandefs.h
+
+Abstract:
+
+ This file contains defines for the NdisWan driver.
+
+Author:
+
+ Tony Bell (TonyBe) June 06, 1995
+
+Environment:
+
+ Kernel Mode
+
+Revision History:
+
+ TonyBe 06/06/95 Created
+
+--*/
+
+#ifndef _NDISWAN_DEFS_
+#define _NDISWAN_DEFS_
+
+//
+// Define if we are going to pull the miniport name out of
+// an ndis wrapper control structure!!!!!! (kinda dirty)
+//
+#define MINIPORT_NAME 1
+
+//
+// Maximum number of protocols we can support
+//
+#define MAX_PROTOCOLS 32
+
+//
+// Identifiers for protocol type being added to the
+// protocol lookup table
+//
+#define PROTOCOL_TYPE 0
+#define PPP_TYPE 1
+
+//
+// Flags for Send packet properties
+//
+#define SEND_ON_WIRE 0x00000001
+#define SELF_DIRECTED 0x00000002
+
+//
+// Known protocol ID's
+//
+#define PROTOCOL_PRIVATE_IO 0xAB00
+#define PROTOCOL_IP 0x0800
+#define PROTOCOL_IPX 0x8137
+#define PROTOCOL_NBF 0x80D5
+
+//
+// Known PPP protocol ID's
+//
+#define PPP_PROTOCOL_PRIVATE_IO 0x00AB
+#define PPP_PROTOCOL_IP 0x0021
+#define PPP_PROTOCOL_UNCOMPRESSED_TCP 0x002F
+#define PPP_PROTOCOL_COMPRESSED_TCP 0x002D
+#define PPP_PROTOCOL_IPX 0x002B
+#define PPP_PROTOCOL_NBF 0x003F
+#define PPP_PROTOCOL_COMPRESSION 0x00FD
+#define PPP_PROTOCOL_COMP_RESET 0x80FD
+
+//
+// Returned from protocol table lookup if value is
+// not found
+//
+#define INVALID_PROTOCOL 0xFFFF
+
+#define RESERVED_PROTOCOLCB 0xFFFFFFFF
+
+//
+// OID Masks
+//
+#define OID_GEN 0x00000000
+#define OID_802_3 0x01000000
+#define OID_WAN 0x04000000
+#define SET_OID 0x00000001
+#define QUERY_OID 0x00000002
+
+#define MAX_FRAME_SIZE 1500
+#define MAX_TOTAL_SIZE 1500
+#define MAX_OUTSTANDING_PACKETS 10
+#define DEFAULT_MAX_MRRU 1600
+#define IO_SEND_MASK_BIT 0x00000001
+#define ONE_HUNDRED_MILS 1000000
+#define ONE_SECOND 10000000
+#define TEN_SECONDS 100000000
+#define MILS_TO_100NANOS 10000
+#define SAMPLE_ARRAY_SIZE 10
+
+//
+// Multilink defines
+//
+#define MULTILINK_BEGIN_FRAME 0x80
+#define MULTILINK_END_FRAME 0x40
+#define MULTILINK_COMPLETE_FRAME 0xC0
+#define MULTILINK_FLAG_MASK 0xC0
+#define SHORT_SEQ_MASK 0x0FFF
+#define TEST_SHORT_SEQ 0x0800
+#define LONG_SEQ_MASK 0x0FFFFFF
+#define TEST_LONG_SEQ 0x00800000
+#define MAX_MRRU 1614
+#define MIN_SEND 1500
+
+#define SEQ_EQ(_a, _b) ((int)((_a) - (_b)) == 0)
+#define SEQ_LT(_a, _b, _t) (!SEQ_EQ(_a, _b) && ((int)((_a) - (_b)) & _t))
+#define SEQ_LTE(_a, _b, _t) (SEQ_EQ(_a, _b) || ((int)((_a) - (_b)) & _t))
+#define SEQ_GT(_a, _b, _t) (!SEQ_EQ(_a, _b) && !((int)((_a) - (_b)) & _t))
+#define SEQ_GTE(_a, _b, _t) (SEQ_EQ(_a, _b) || !((int)((_a) - (_b)) & _t))
+
+//
+// Debugging
+//
+#define DBG_DEATH 1
+#define DBG_CRITICAL_ERROR 2
+#define DBG_FAILURE 4
+#define DBG_INFO 6
+#define DBG_TRACE 8
+#define DBG_VERBOSE 10
+
+#define DBG_INIT 0x00000001
+#define DBG_MINIPORT 0x00000002
+#define DBG_PROTOCOL 0x00000004
+#define DBG_SEND 0x00000008
+#define DBG_RECEIVE 0x00000010
+#define DBG_IO 0x00000020
+#define DBG_MEMORY 0x00000040
+#define DBG_VJ 0x00000080
+#define DBG_TAPI 0x00000100
+#define DBG_CCP 0x00000200
+#define DBG_LOOPBACK 0x00000400
+#define DBG_MULTILINK_RECV 0x00000800
+#define DBG_MULTILINK_SEND 0x00001000
+#define DBG_SEND_VJ 0x00002000
+#define DBG_RECV_VJ 0x00004000
+#define DBG_ALL 0xFFFFFFFF
+
+//
+// Link State's
+//
+typedef enum _LinkState {
+ LINK_DOWN,
+ LINK_GOING_DOWN,
+ LINK_UP
+} LinkState;
+
+//
+// Bundle State's
+//
+typedef enum _BundleState {
+ BUNDLE_DOWN,
+ BUNDLE_GOING_DOWN,
+ BUNDLE_UP
+} BundleState;
+
+//
+// Wan request types
+//
+typedef enum _WanRequestType {
+ ASYNC,
+ SYNC
+} WanRequestType;
+
+typedef enum _WanRequestOrigin {
+ NDISWAN,
+ NDISTAPI
+} WanRequestOrigin;
+
+typedef enum _BandwidthOnDemandState {
+ BonDIdle,
+ BonDMonitor,
+ BonDSignaled
+} BandwithOnDemandState;
+
+typedef enum _DeferredQueueType {
+ ReceiveIndication,
+ SendComplete,
+ StatusIndication,
+ Loopback
+} DeferredQueueType;
+
+#define MAX_DEFERRED_QUEUE_TYPES 4
+
+typedef enum _DeferredType {
+ LineUp = MAX_DEFERRED_QUEUE_TYPES,
+ LineDown
+} DeferredType;
+
+#define BUNDLEH_FROM_BUNDLECB(_pbcb) _pbcb->hBundleHandle
+#define BUNDLECB_FROM_LINKCB(_plcb) (PBUNDLECB)_plcb->BundleCB
+#define BUNDLECB_FROM_BUNDLEH(_pbcb, _bh) \
+{ \
+ NdisAcquireSpinLock(&ConnectionTable->Lock); \
+ if ((ULONG)_bh <= ConnectionTable->ulArraySize) { \
+ _pbcb = *(ConnectionTable->BundleArray + (ULONG)_bh); \
+ } else { \
+ _pbcb = NULL; \
+ } \
+ NdisReleaseSpinLock(&ConnectionTable->Lock); \
+}
+
+#define LINKH_FROM_LINKCB(_plcb) _plcb->hLinkHandle
+#define LINKCB_FROM_LINKH(_plcb, _lh) \
+{ \
+ NdisAcquireSpinLock(&ConnectionTable->Lock); \
+ if ((ULONG)_lh <= ConnectionTable->ulArraySize) { \
+ _plcb = *(ConnectionTable->LinkArray + (ULONG)_lh); \
+ } else { \
+ _plcb = NULL; \
+ } \
+ NdisReleaseSpinLock(&ConnectionTable->Lock); \
+}
+
+#define GetGlobalListCount(_gl, _ul) \
+{ \
+ NdisAcquireSpinLock(&(_gl.Lock)); \
+ _ul = _gl.ulCount; \
+ NdisReleaseSpinLock(&(_gl.Lock)); \
+}
+
+#define InsertTailGlobalList(_gl, _ple) \
+{ \
+ NdisAcquireSpinLock(&(_gl.Lock)); \
+ InsertTailList(&(_gl.List), _ple); \
+ _gl.ulCount++; \
+ NdisReleaseSpinLock(&(_gl.Lock)); \
+}
+
+#define InsertHeadGlobalList(_gl, _ple) \
+{ \
+ NdisAcquireSpinLock(&(_gl.Lock)); \
+ InsertHeadList(&(_gl.List), _ple); \
+ _gl.ulCount++; \
+ NdisReleaseSpinLock(&(_gl.Lock)); \
+}
+
+#define RemoveHeadGlobalList(_gl, _ple) \
+{ \
+ NdisAcquireSpinLock(&(_gl.Lock)); \
+ _ple = RemoveHeadList(&(_gl.List)); \
+ _gl.ulCount--; \
+ NdisReleaseSpinLock(&(_gl.Lock)); \
+}
+
+//
+// The Remote address (DEST address) is what we use to mutilplex
+// sends across our single adapter/binding context. The address
+// has the following format:
+//
+// XX XX XX YY YY ZZ
+//
+// XX = Randomly generated OUI
+// YY = Index into the active bundle connection table to get bundlecb
+// ZZ = Index into the protocol table of a bundle to get protocolcb
+//
+#define FillNdisWanBundleIndex(_pAddr, _Index) \
+{ \
+ _pAddr[3] = (UCHAR)((USHORT)_Index >> 8); \
+ _pAddr[4] = (UCHAR)_Index; \
+}
+
+#define GetNdisWanBundleIndex(_pAddr, _Index) \
+{ \
+ _Index = ((USHORT)_pAddr[3] << 8) | _pAddr[4]; \
+}
+
+#define FillNdisWanProtocolIndex(_pAddr, _Index) _pAddr[5] = (UCHAR)_Index
+
+#define GetNdisWanProtocolIndex(_pAddr, _Index) \
+{ \
+ _Index = _pAddr[5]; \
+ ASSERT(_Index != 0); \
+ if (_Index == 0) { \
+ _Index = MAX_PROTOCOLS + 1; \
+ } \
+}
+
+//
+// In the Src address (from a NdisSend) the bundle index
+// is stashed in the two high order bytes as shown below
+// with the mask of valid bits given by the x's. The
+// high byte is shifted to the left one bit so the number
+// of possible bundles is now 0x7FFF
+//
+// 0 1
+// 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
+// x x x x x x x 0 x x x x x x x x
+//
+#define FillTransportBundleIndex(_pAddr, _Index) \
+{ \
+ _pAddr[0] = (UCHAR)((USHORT)_Index >> 7) & 0xFE; \
+ _pAddr[1] = (UCHAR)_Index; \
+}
+
+#define GetTransportBundleIndex(_pAddr, _Index) \
+{ \
+ _Index = (((USHORT)_pAddr[0] << 7) & 0x7F) | _pAddr[1]; \
+} \
+
+#define GetProtocolIndexFromProtocolList(_pl, _pt, _Index) \
+{ \
+ PPROTOCOLCB _pP; \
+ \
+ _Index = MAX_PROTOCOLS + 1; \
+ \
+ for (_pP = (PPROTOCOLCB)(_pl)->Flink; \
+ (PLIST_ENTRY)_pP != _pl; \
+ _pP = (PPROTOCOLCB)(_pP)->Linkage.Flink) { \
+ \
+ if (_pP->usProtocolType == _pt) { \
+ _Index = (ULONG)_pP->hProtocolHandle; \
+ break; \
+ } \
+ } \
+}
+
+#define ProtocolCBFromProtocolH(_pBCB, _hP, _pPCB) \
+{ \
+ ASSERT(_hP != 0); \
+ if (_hP < MAX_PROTOCOLS) { \
+ _pPCB = _pBCB->ProtocolCBTable[_hP]; \
+ } \
+}
+
+#define IsValidProtocolCB(_pPCB) \
+ (_pPCB != NULL && _pPCB != (PPROTOCOLCB)RESERVED_PROTOCOLCB)
+
+#define NetToHostShort(_ns) ( ((_ns & 0x00FF) << 8) | ((_ns & 0xFF00) >> 8) )
+#define HostToNetShort(_hs) ( ((_hs & 0x00FF) << 8) | ((_hs & 0xFF00) >> 8) )
+
+#define IsLinkSendWindowOpen(_plcb) ((_plcb)->ulWanPacketCount > 1)
+
+#define UpdateProtocolQuota(_pPCB, _ulBytes) UpdateSampleTable(&(_pPCB->SampleTable), _ulBytes)
+
+#define PMINIPORT_RESERVED_FROM_NDIS(_packet) \
+ ((PNDISWAN_MINIPORT_RESERVED)((_packet)->MiniportReserved))
+
+#define IsCompleteFrame(_fl) \
+ ((_fl & MULTILINK_BEGIN_FRAME) && (_fl & MULTILINK_END_FRAME))
+
+#define AddPPPProtocolID(_finf, _usID) \
+{ \
+ PUCHAR _cp = _finf->ProtocolID.Pointer; \
+ if (_finf->ProtocolID.Length != 0) { \
+ ASSERT(_cp); \
+ if (!(_finf->FramingBits & PPP_COMPRESS_PROTOCOL_FIELD) || \
+ (_finf->Flags & (DO_COMPRESSION | DO_ENCRYPTION))) { \
+ *_cp++ = (UCHAR)(_usID >> 8); \
+ } \
+ *_cp = (UCHAR)_usID; \
+ } \
+}
+
+#define AddMultilinkInfo(_finf, _f, _seq, _mask) \
+{ \
+ PUCHAR _cp = _finf->Multilink.Pointer; \
+ if (_finf->Multilink.Length != 0) { \
+ ASSERT(_cp); \
+ if (!(_finf->FramingBits & PPP_COMPRESS_PROTOCOL_FIELD)) { \
+ _cp++; \
+ } \
+ _cp++; \
+ _seq &= _mask; \
+ if (_finf->FramingBits & PPP_SHORT_SEQUENCE_HDR_FORMAT) { \
+ *_cp++ = _f | (UCHAR)((_seq >> 8) & SHORT_SEQ_MASK); \
+ *_cp++ = (UCHAR)_seq; \
+ } else { \
+ *_cp++ = _f; \
+ *_cp++ = (UCHAR)(_seq >> 16); \
+ *_cp++ = (UCHAR)(_seq >> 8); \
+ *_cp = (UCHAR)_seq; \
+ } \
+ } \
+}
+
+#define AddCompressionInfo(_finf, _usCC) \
+{ \
+ PUCHAR _cp = _finf->Compression.Pointer; \
+ if (_finf->Compression.Length != 0) { \
+ ASSERT(_cp); \
+ if (!(_finf->FramingBits & PPP_COMPRESS_PROTOCOL_FIELD)) { \
+ _cp++; \
+ } \
+ _cp++; \
+ *_cp++ = (UCHAR)(_usCC >> 8); \
+ *_cp = (UCHAR)_usCC; \
+ } \
+}
+
+#ifdef USE_NDIS_MINIPORT_LOCKING
+
+#define NdisWanAcquireMiniportLock(_a) \
+ NdisIMSwitchToMiniport((_a)->hMiniportHandle, &((_a)->SwitchHandle))
+
+#define NdisWanReleaseMiniportLock(_a) \
+ NdisIMRevertBack((_a)->hMiniportHandle, (_a)->SwitchHandle)
+
+#endif // end of use_ndis_miniport_locking
+
+
+#ifdef USE_NDIS_MINIPORT_CALLBACK
+
+#define NdisWanSetDeferred(_a) \
+{ \
+ if (!((_a)->Flags & DEFERRED_CALLBACK_SET)) { \
+ (_a)->Flags |= DEFERRED_CALLBACK_SET; \
+ NdisIMQueueMiniportCallback((_a)->hMiniportHandle, DeferredCallback, (_a)); \
+ } \
+}
+
+#else // end of USE_NDIS_MINIPORT_CALLBACK
+
+#define NdisWanSetDeferred(_a) \
+{ \
+ if (!((_a)->Flags & DEFERRED_TIMER_SET)) { \
+ (_a)->Flags |= DEFERRED_TIMER_SET; \
+ NdisMSetTimer(&((_a)->DeferredTimer), 15); \
+ } \
+}
+#endif // end of !USE_NDIS_MINIPORT_CALLBACK
+
+#define NdisWanChangeMiniportAddress(_a, _addr) \
+{ \
+ PNDIS_MINIPORT_BLOCK Miniport; \
+ \
+ Miniport = (PNDIS_MINIPORT_BLOCK)((_a)->hMiniportHandle); \
+ ETH_COPY_NETWORK_ADDRESS(Miniport->EthDB->AdapterAddress, _addr); \
+}
+
+//
+// Queue routines for the deferred work queues
+//
+#define IsDeferredQueueEmpty(_pq) ((_pq)->Head == NULL)
+
+#define InsertHeadDeferredQueue(_pq, _pe) \
+{ \
+ if (((_pe)->Next = (_pq)->Head) == NULL) { \
+ (_pq)->Tail = (_pe); \
+ } \
+ (_pq)->Head = (_pe); \
+ if (++(_pq)->Count > (_pq)->MaxCount) { \
+ (_pq)->MaxCount++; \
+ } \
+}
+
+#define InsertTailDeferredQueue(_pq, _pe) \
+{ \
+ (_pe)->Next = NULL; \
+ if ((_pq)->Head == NULL) { \
+ (_pq)->Head = (_pe); \
+ } else { \
+ (_pq)->Tail->Next = (_pe); \
+ } \
+ (_pq)->Tail = (_pe); \
+ if (++(_pq)->Count > (_pq)->MaxCount) { \
+ (_pq)->MaxCount++; \
+ } \
+}
+
+#define RemoveHeadDeferredQueue(_pq) \
+ (_pq)->Head; \
+ { \
+ if ((_pq)->Head->Next == NULL) { \
+ (_pq)->Tail = NULL; \
+ } \
+ (_pq)->Head = (_pq)->Head->Next; \
+ (_pq)->Count--; \
+ }
+
+
+//
+// Queue routines for the ProtocolCB's NdisPacket queues
+//
+#define InsertHeadNdisPacketQueue(_ppcb, _pnp) \
+{ \
+ PMINIPORT_RESERVED_FROM_NDIS(_pnp)->Next = \
+ (_ppcb)->HeadNdisPacketQueue; \
+ \
+ if ((_ppcb)->HeadNdisPacketQueue == NULL) { \
+ (_ppcb)->TailNdisPacketQueue = _pnp; \
+ } \
+ \
+ (_ppcb)->HeadNdisPacketQueue = _pnp; \
+}
+
+#define InsertTailNdisPacketQueue(_ppcb, _pnp) \
+{ \
+ PMINIPORT_RESERVED_FROM_NDIS(_pnp)->Next = NULL; \
+ \
+ if ((_ppcb)->HeadNdisPacketQueue == NULL) { \
+ (_ppcb)->HeadNdisPacketQueue = _pnp; \
+ } else { \
+ PMINIPORT_RESERVED_FROM_NDIS((_ppcb)->TailNdisPacketQueue)->Next = _pnp; \
+ } \
+ \
+ (_ppcb)->TailNdisPacketQueue = _pnp; \
+}
+
+#define RemoveHeadNdisPacketQueue(_ppcb) \
+ (_ppcb)->HeadNdisPacketQueue; \
+ { \
+ PNDIS_PACKET _FirstPacket = \
+ PMINIPORT_RESERVED_FROM_NDIS((_ppcb)->HeadNdisPacketQueue)->Next; \
+ \
+ if (_FirstPacket == NULL) { \
+ (_ppcb)->TailNdisPacketQueue = NULL; \
+ } \
+ \
+ (_ppcb)->HeadNdisPacketQueue = _FirstPacket; \
+ }
+
+#define IsNdisPacketQueueEmpty(_ppcb) ((_ppcb)->HeadNdisPacketQueue == NULL)
+
+#define NdisWanDoReceiveComplete(_pa) \
+{ \
+ NdisReleaseSpinLock(&(_pa)->Lock); \
+ NdisMEthIndicateReceiveComplete((_pa)->hMiniportHandle); \
+ NdisAcquireSpinLock(&(_pa)->Lock); \
+}
+
+#define NDISM_PROCESS_DEFERRED(_M) (_M)->ProcessDeferredHandler((_M))
+
+//
+// OS specific code
+//
+#ifdef NT
+
+//
+// NT stuff
+//
+#define NdisWanInitializeNotificationEvent(_pEvent) KeInitializeEvent(_pEvent, NotificationEvent, FALSE)
+#define NdisWanSetNotificationEvent(_pEvent) KeSetEvent(_pEvent, 0, FALSE)
+#define NdisWanClearNotificationEvent(_pEvent) KeClearEvent(_pEvent)
+#define NdisWanWaitForNotificationEvent(_pEvent) KeWaitForSingleObject(_pEvent, Executive, KernelMode, TRUE, NULL)
+
+#define NdisWanInitializeSyncEvent(_pEvent) KeInitializeEvent(_pEvent, SynchronizationEvent, FALSE)
+#define NdisWanSetSyncEvent(_pEvent) KeSetEvent(_pEvent, 1, FALSE)
+#define NdisWanClearSyncEvent(_pEvent) KeClearEvent(_pEvent)
+#define NdisWanWaitForSyncEvent(_pEvent) KeWaitForSingleObject(_pEvent, UserRequest, KernelMode, FALSE, NULL)
+
+#define NdisWanAllocateMemory(_AllocatedMemory, _Size) \
+{ \
+ (PVOID)*(_AllocatedMemory) = (PVOID)ExAllocatePoolWithTag(NonPagedPool, _Size, ' naW'); \
+ ASSERT((PVOID)*(_AllocatedMemory) != NULL); \
+ if ((PVOID)*(_AllocatedMemory) != NULL) { \
+ NdisZeroMemory((PUCHAR)*(_AllocatedMemory), _Size); \
+ } \
+}
+
+#define NdisWanFreeMemory(_AllocatedMemory) ExFreePool(_AllocatedMemory)
+#define NdisWanMoveMemory(_Dest, _Src, _Length) RtlMoveMemory(_Dest, _Src, _Length)
+
+#define NdisWanGetSystemTime(_pTime) KeQuerySystemTime(_pTime)
+
+#define NdisWanCalcTimeDiff(_pDest, _pEnd, _pBegin) \
+ (_pDest)->QuadPart = (_pEnd)->QuadPart - (_pBegin)->QuadPart
+
+#define NdisWanInitWanTime(_pTime, _Val) (_pTime)->QuadPart = _Val
+
+#define NdisWanMultiplyWanTime(_pDest, _pMulti1, _pMulti2) \
+ (_pDest)->QuadPart = (_pMulti1)->QuadPart * (_pMulti2)->QuadPart
+
+#define NdisWanDivideWanTime(_pDest, _pDivi1, _pDivi2) \
+ (_pDest)->QuadPart = (_pDivi1)->QuadPart / (_pDivi2)->QuadPart
+
+#define NdisWanIsTimeDiffLess(_pTime1, _pTime2) ((_pTime1)->QuadPart < (_pTime2)->QuadPart)
+#define NdisWanIsTimeDiffGreater(_pTime1, _pTime2) ((_pTime1)->QuadPart > (_pTime2)->QuadPart)
+#define NdisWanIsTimeEqual(_pTime1, _pTime2) ((_pTime1)->QuadPart == (_pTime2)->QuadPart)
+
+#define NdisWanUppercaseNdisString(_pns1, _pns2, _b) RtlUpcaseUnicodeString(_pns1, _pns2, _b)
+#define MDL_ADDRESS(_MDL_) MmGetSystemAddressForMdl(_MDL_)
+
+#define NdisWanInterlockedInc(_pul) InterlockedIncrement(_pul)
+#define NdisWanInterlockedDec(_pul) InterlockedDecrement(_pul)
+#define NdisWanInterlockedExchange(_pul, ul) InterlockedExchange(_pul, ul)
+#define NdisWanExInterlockedExchange(_pul, ul, _plock) ExInterlockedExchangeUlong(_pul, ul, _plock)
+
+#define NdisWanInterlockedInsertTailList(_phead, _pentry, _plock) \
+ ExInterlockedInsertTailList(_phead, _pentry, _plock)
+
+#define NdisWanInterlockedInsertHeadList(_phead, _pentry, _plock) \
+ ExInterlockedInsertHeadList(_phead, _pentry, _plock)
+
+#define NdisWanInterlockedRemoveHeadList(_phead, _plock) \
+ ExInterlockedRemoveHeadList(_phead, _plock)
+
+#define NdisWanRaiseIrql(_pirql) KeRaiseIrql(DISPATCH_LEVEL, _pirql)
+#define NdisWanLowerIrql(_irql) KeLowerIrql(_irql)
+//
+// Wait for event structure. Used for async completion notification.
+//
+typedef KEVENT WAN_EVENT;
+typedef WAN_EVENT *PWAN_EVENT;
+
+typedef LARGE_INTEGER WAN_TIME;
+typedef WAN_TIME *PWAN_TIME;
+
+typedef KIRQL WAN_IRQL;
+typedef WAN_IRQL *PWAN_IRQL;
+
+#if DBG // If built with debug
+
+#define NdisWanDbgOut(_DebugLevel, _DebugMask, _Out) { \
+ if ((NdisWanCB.ulTraceLevel >= _DebugLevel) && \
+ (_DebugMask & NdisWanCB.ulTraceMask)) { \
+ DbgPrint("NDISWAN: "); \
+ DbgPrint _Out; \
+ DbgPrint("\n"); \
+ } \
+}
+
+#undef ASSERT
+#define ASSERT(exp) \
+{ \
+ if (!(exp)) { \
+ DbgPrint("NDISWAN: ASSERTION FAILED! %s\n", #exp); \
+ DbgPrint("NDISWAN: File: %s, Line: %d\n", __FILE__, __LINE__); \
+ DbgBreakPoint(); \
+ } \
+}
+
+#else // If not built with debug
+
+#define NdisWanDbgOut(_DebugLevel, _DebugMask, _Out)
+
+#endif // end DBG
+
+#else // end NT stuff
+//
+// Win95 stuff
+//
+
+typedef ULONG WAN_TIME;
+typedef WAN_TIME *PWAN_TIME;
+
+#endif
+
+#endif
diff --git a/private/ntos/ndis/ndiswan/wanproto.h b/private/ntos/ndis/ndiswan/wanproto.h
new file mode 100644
index 000000000..e8e515aa5
--- /dev/null
+++ b/private/ntos/ndis/ndiswan/wanproto.h
@@ -0,0 +1,696 @@
+/*++
+
+Copyright (c) 1990-1995 Microsoft Corporation
+
+Module Name:
+
+ Wanproto.h
+
+Abstract:
+
+ This file contains the prototypes for functions that NdisWan uses.
+
+Author:
+
+ Tony Bell (TonyBe) June 06, 1995
+
+Environment:
+
+ Kernel Mode
+
+Revision History:
+
+ TonyBe 06/06/95 Created
+
+--*/
+
+#ifndef _NDISWAN_PROTO
+#define _NDISWAN_PROTO
+
+//
+// Functions from ccp.c
+//
+VOID
+WanDeallocateCCP(
+ PBUNDLECB BundleCB
+ );
+
+NTSTATUS
+WanAllocateCCP(
+ PBUNDLECB BundleCB
+ );
+
+//
+// Functions from indicate.c
+//
+VOID
+NdisWanLineUpIndication(
+ IN PWAN_ADAPTERCB WanAdapterCB,
+ IN PUCHAR Buffer,
+ IN ULONG BufferSize
+ );
+
+VOID
+NdisWanLineDownIndication(
+ IN PWAN_ADAPTERCB WanAdapterCB,
+ IN PUCHAR Buffer,
+ IN ULONG BufferSize
+ );
+
+VOID
+NdisWanFragmentIndication(
+ IN PWAN_ADAPTERCB WanAdapterCB,
+ IN PUCHAR Buffer,
+ IN ULONG BufferSize
+ );
+
+VOID
+UpdateBundleInfo(
+ IN PBUNDLECB BundleCB
+ );
+
+VOID
+AddLinkToBundle(
+ IN PBUNDLECB BundleCB,
+ IN PLINKCB LinkCB
+ );
+
+VOID
+RemoveLinkFromBundle(
+ IN PBUNDLECB BundleCB,
+ IN PLINKCB LinkCB
+ );
+
+VOID
+FreeBundleResources(
+ PBUNDLECB BundleCB
+ );
+
+//
+// Functions from io.c
+//
+#ifdef NT
+
+NTSTATUS
+NdisWanIoctl(
+ IN PDEVICE_OBJECT pDeviceObject,
+ IN PIRP pIrp
+ );
+
+VOID
+NdisWanCancelRoutine(
+ IN PDEVICE_OBJECT pDeviceObject,
+ IN PIRP pIrp
+ );
+
+NTSTATUS
+NdisWanIrpStub(
+ IN PDEVICE_OBJECT pDeviceObject,
+ IN PIRP pIrp
+ );
+
+#endif // NT
+
+//
+// Functions from loopback.c
+//
+
+VOID
+NdisWanQueueLoopbackPacket(
+ PADAPTERCB AdapterCB,
+ PNDIS_PACKET NdisPacket
+ );
+
+VOID
+NdisWanProcessLoopbacks(
+ PADAPTERCB AdapterCB
+ );
+
+//
+// Functions from memory.c
+//
+NDIS_STATUS
+NdisWanCreateAdapterCB(
+ OUT PADAPTERCB *pAdapterCB,
+ IN PNDIS_STRING AdapterName
+ );
+
+VOID
+NdisWanDestroyAdapterCB(
+ IN PADAPTERCB pAdapterCB
+ );
+
+NDIS_STATUS
+NdisWanCreateWanAdapterCB(
+ IN PWSTR BindName
+ );
+
+VOID
+NdisWanDestroyWanAdapterCB(
+ IN PWAN_ADAPTERCB pWanAdapterCB
+ );
+
+VOID
+NdisWanGetProtocolCB(
+ OUT PPROTOCOLCB *ProtocolCB,
+ IN USHORT usProtocolType,
+ IN USHORT usDeviceNameLength,
+ IN PWSTR DeviceName,
+ IN ULONG ulBufferLength,
+ IN PUCHAR Buffer
+ );
+
+VOID
+NdisWanReturnProtocolCB(
+ IN PPROTOCOLCB ProtocolCB
+ );
+
+VOID
+NdisWanGetLinkCB(
+ OUT PLINKCB *LinkCB,
+ IN PWAN_ADAPTERCB WanAdapterCB,
+ IN ULONG SendWindow
+ );
+
+VOID
+NdisWanReturnLinkCB(
+ PLINKCB LinkCB
+ );
+
+
+VOID
+NdisWanGetBundleCB(
+ OUT PBUNDLECB *BundleCB
+ );
+
+VOID
+NdisWanReturnBundleCB(
+ IN PBUNDLECB BundleCB
+ );
+
+NDIS_STATUS
+NdisWanCreatePPPProtocolTable(
+ VOID
+ );
+
+VOID
+NdisWanDestroyPPPProtocolTable(
+ VOID
+ );
+
+NDIS_STATUS
+NdisWanCreateConnectionTable(
+ ULONG TableSize
+ );
+
+VOID
+NdisWanDestroyConnectionTable(
+ VOID
+ );
+
+VOID
+CompleteThresholdEvent(
+ PBUNDLECB BundleCB,
+ ULONG ThresholdType
+ );
+
+VOID
+NdisWanGetDeferredDesc(
+ PADAPTERCB AdapterCB,
+ PDEFERRED_DESC *RetDesc
+ );
+
+//
+// Functions from ndiswan.c
+//
+NDIS_STATUS
+DoMiniportInit(
+ VOID
+ );
+
+NDIS_STATUS
+DoProtocolInit(
+ IN PUNICODE_STRING RegistryPath
+ );
+
+NDIS_STATUS
+DoWanMiniportInit(
+ VOID
+ );
+
+VOID
+NdisWanReadRegistry(
+ IN PUNICODE_STRING RegistryPath
+ );
+
+VOID
+NdisWanGlobalCleanup(
+ VOID
+ );
+
+VOID
+InsertPPP_ProtocolID(
+ IN ULONG Value,
+ IN ULONG ValueType
+ );
+
+USHORT
+GetPPP_ProtocolID(
+ IN USHORT Value,
+ IN ULONG ValueType
+ );
+
+NDIS_HANDLE
+InsertLinkInConnectionTable(
+ IN PLINKCB LinkCB
+ );
+
+VOID
+RemoveLinkFromConnectionTable(
+ IN PLINKCB LinkCB
+ );
+
+NDIS_HANDLE
+InsertBundleInConnectionTable(
+ IN PBUNDLECB BundleCB
+ );
+
+VOID
+RemoveBundleFromConnectionTable(
+ IN PBUNDLECB BundleCB
+ );
+
+NTSTATUS
+BindQueryRoutine(
+ IN PWSTR ValueName,
+ IN ULONG ValueType,
+ IN PVOID ValueData,
+ IN ULONG ValueLength,
+ IN PVOID Context,
+ IN PVOID EntryContext
+ );
+
+NTSTATUS
+ProtocolTypeQueryRoutine(
+ IN PWSTR ValueName,
+ IN ULONG ValueType,
+ IN PVOID ValueData,
+ IN ULONG ValueLength,
+ IN PVOID Context,
+ IN PVOID EntryContext
+ );
+
+BOOLEAN
+IsHandleValid(
+ USHORT usHandleType,
+ NDIS_HANDLE hHandle
+ );
+
+#if DBG
+
+PUCHAR
+NdisWanGetNdisStatus(
+ IN NDIS_STATUS GeneralStatus
+ );
+
+#endif
+
+
+//
+// Functions from miniport.c
+//
+
+BOOLEAN
+NdisWanCheckForHang(
+ IN NDIS_HANDLE MiniportAdapterContext
+ );
+
+NDIS_STATUS
+NdisWanQueryInformation(
+ IN NDIS_HANDLE MiniportAdapterContext,
+ IN NDIS_OID Oid,
+ IN PVOID InformationBuffer,
+ IN ULONG InformationBufferLength,
+ OUT PULONG BytesWritten,
+ OUT PULONG BytesNeeded
+ );
+
+NDIS_STATUS
+NdisWanSetInformation(
+ IN NDIS_HANDLE MiniportAdapterContext,
+ IN NDIS_OID Oid,
+ IN PVOID InformationBuffer,
+ IN ULONG InformationBufferLength,
+ OUT PULONG BytesWritten,
+ OUT PULONG BytesNeeded
+ );
+
+VOID
+NdisWanHalt(
+ IN NDIS_HANDLE MiniportAdapterContext
+ );
+
+NDIS_STATUS
+NdisWanInitialize(
+ OUT PNDIS_STATUS OpenErrorStatus,
+ OUT PUINT SelectedMediumIndex,
+ IN PNDIS_MEDIUM MediumArray,
+ IN UINT MediumArraySize,
+ IN NDIS_HANDLE MiniportAdapterHandle,
+ IN NDIS_HANDLE WrapperConfigurationContext
+ );
+
+NDIS_STATUS
+NdisWanReconfigure(
+ OUT PNDIS_STATUS OpenErrorStatus,
+ IN NDIS_HANDLE MiniportAdapterContext,
+ IN NDIS_HANDLE WrapperConfigurationContext
+ );
+
+NDIS_STATUS
+NdisWanReset(
+ OUT PBOOLEAN AddressingReset,
+ IN NDIS_HANDLE MiniportAdapterContext
+ );
+
+#ifdef USE_NDIS_MINIPORT_CALLBACK
+VOID
+DeferredCallback(
+ PADAPTERCB AdapterCB,
+ PVOID Context
+ );
+#endif // end of USE_NDIS_MINIPORT_CALLBACK
+
+//
+// Functions from protocol.c
+//
+
+NDIS_STATUS
+NdisWanOpenWanAdapter(
+ PWAN_ADAPTERCB pWanAdapterCB
+ );
+
+VOID
+NdisWanOpenAdapterComplete(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN NDIS_STATUS Status,
+ IN NDIS_STATUS OpenErrorStatus
+ );
+
+VOID
+NdisWanCloseAdapterComplete(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN NDIS_STATUS Status
+ );
+
+VOID
+NdisWanResetComplete(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN NDIS_STATUS Status
+ );
+
+VOID
+NdisWanTransferDataComplete(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN PNDIS_PACKET pNdisPacket,
+ IN NDIS_STATUS Status,
+ IN UINT BytesTransferred
+ );
+
+VOID
+NdisWanRequestComplete(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN PNDIS_REQUEST NdisRequest,
+ IN NDIS_STATUS Status
+ );
+
+VOID
+NdisWanIndicateStatusComplete(
+ IN NDIS_HANDLE BindingContext
+ );
+
+VOID
+NdisWanIndicateStatus(
+ IN NDIS_HANDLE BindingContext,
+ IN NDIS_STATUS GeneralStatus,
+ IN PVOID StatusBuffer,
+ IN UINT StatusBufferSize
+ );
+
+NDIS_STATUS
+DoNewLineUpToProtocol(
+ IN PPROTOCOLCB ProtocolCB
+ );
+
+NDIS_STATUS
+DoLineUpToProtocol(
+ IN PPROTOCOLCB ProtocolCB
+ );
+
+NDIS_STATUS
+DoLineDownToProtocol(
+ PPROTOCOLCB ProtocolCB
+ );
+
+VOID
+NdisWanProcessStatusIndications(
+ PADAPTERCB AdapterCB
+ );
+
+//
+// Functions from receive.c
+//
+NDIS_STATUS
+NdisWanReceiveIndication(
+ IN NDIS_HANDLE NdisLinkContext,
+ IN PUCHAR Packet,
+ IN ULONG PacketSize
+ );
+
+VOID
+NdisWanReceiveComplete(
+ IN NDIS_HANDLE NdisLinkContext
+ );
+
+NDIS_STATUS
+NdisWanTransferData(
+ OUT PNDIS_PACKET NdisPacket,
+ OUT PUINT BytesTransferred,
+ IN NDIS_HANDLE MiniportAdapterContext,
+ IN NDIS_HANDLE MiniportReceiveContext,
+ IN UINT ByteOffset,
+ IN UINT BytesToTransfer
+ );
+
+VOID
+FlushRecvDescAssemblyList(
+ IN PBUNDLECB BundleCB
+ );
+
+VOID
+FreeRecvDescFreeList(
+ IN PBUNDLECB BundleCB
+ );
+
+VOID
+NdisWanGetRecvDesc(
+ PBUNDLECB BundleCB,
+ PRECV_DESC *ReturnRecvDesc
+ );
+
+VOID
+RecvFlushFunction(
+ PVOID System1,
+ PVOID Context,
+ PVOID System2,
+ PVOID System3
+ );
+
+VOID
+NdisWanProcessReceiveIndications(
+ PADAPTERCB AdapterCB
+ );
+
+BOOLEAN
+IpIsDataFrame(
+ PUCHAR HeaderBuffer,
+ ULONG HeaderBufferLength,
+ ULONG TotalLength
+ );
+
+BOOLEAN
+IpxIsDataFrame(
+ PUCHAR HeaderBuffer,
+ ULONG HeaderBufferLength,
+ ULONG TotalLength
+ );
+
+BOOLEAN
+NbfIsDataFrame(
+ PUCHAR HeaderBuffer,
+ ULONG HeaderBufferLength,
+ ULONG TotalLength
+ );
+
+
+//
+// Functions from request.c
+//
+
+NDIS_STATUS
+NdisWanSubmitNdisRequest(
+ IN PWAN_ADAPTERCB pWanAdapterCB,
+ IN PNDIS_REQUEST pNdisRequest,
+ IN WanRequestType Type,
+ IN WanRequestOrigin Origin
+ );
+
+NDIS_STATUS
+NdisWanOidProc(
+ IN PADAPTERCB pAdapterCB,
+ IN NDIS_OID Oid,
+ IN ULONG SetQueryFlag,
+ IN PVOID InformationBuffer,
+ IN ULONG InformationBufferLength,
+ OUT PULONG BytesWritten,
+ OUT PULONG BytesNeeded
+ );
+
+PWAN_REQUEST
+GetWanRequest(
+ IN PWAN_ADAPTERCB pWanAdapterCB,
+ IN PNDIS_REQUEST pNdisRequest
+ );
+
+VOID
+AddRequestToList(
+ IN PWAN_ADAPTERCB pWanAdapterCB,
+ IN PWAN_REQUEST pWanRequest
+ );
+
+VOID
+RemoveRequestFromList(
+ IN PWAN_ADAPTERCB pWanAdapterCB,
+ IN PWAN_REQUEST pWanRequest
+ );
+
+//
+// Functions from send.c
+//
+NDIS_STATUS
+NdisWanSend(
+ IN NDIS_HANDLE MiniportAdapterContext,
+ IN PNDIS_PACKET pNdisPacket,
+ IN UINT Flags
+ );
+
+VOID
+NdisWanSendCompleteHandler(
+ IN NDIS_HANDLE ProtocolBindingContext,
+ IN PNDIS_WAN_PACKET pNdisWanPacket,
+ IN NDIS_STATUS NdisStatus
+);
+
+VOID
+NdisWanProcessSendCompletes(
+ PADAPTERCB AdapterCB
+ );
+
+NDIS_STATUS
+BuildIoPacket(
+ IN PNDISWAN_IO_PACKET pWanIoPacket,
+ IN BOOLEAN SendImmediate
+ );
+
+VOID
+NdisWanCopyFromPacketToBuffer(
+ IN PNDIS_PACKET NdisPacket,
+ IN ULONG Offset,
+ IN ULONG BytesToCopy,
+ OUT PUCHAR Buffer,
+ OUT PULONG BytesCopied
+ );
+
+VOID
+TryToCompleteNdisPacket(
+ PADAPTERCB AdapterCB,
+ PNDIS_PACKET NdisPacket
+ );
+//
+// Functions from tapi.c
+//
+
+NDIS_STATUS
+NdisWanTapiRequestProc(
+ PWAN_ADAPTERCB WanAdapterCB,
+ PNDIS_REQUEST NdisRequest
+ );
+
+VOID
+NdisWanTapiRequestComplete(
+ PWAN_ADAPTERCB WanAdapterCB,
+ PWAN_REQUEST WanRequest
+ );
+
+VOID
+NdisWanTapiIndication(
+ PWAN_ADAPTERCB WanAdapterCB,
+ PUCHAR StatusBuffer,
+ ULONG StatusBufferSize
+ );
+
+//
+// Function from util.c
+//
+
+VOID
+NdisWanStringToNdisString(
+ IN PNDIS_STRING pDestString,
+ IN PWSTR pSrcBuffer
+ );
+
+VOID
+NdisWanAllocateAdapterName(
+ PNDIS_STRING Dest,
+ PNDIS_STRING Src
+ );
+
+VOID
+NdisWanFreeNdisString(
+ IN PNDIS_STRING NdisString
+ );
+
+BOOLEAN
+NdisWanCompareNdisString(
+ PNDIS_STRING NdisString1,
+ PNDIS_STRING NdisString2
+ );
+
+VOID
+NdisWanNdisStringToInteger(
+ IN PNDIS_STRING Source,
+ IN PULONG Value
+ );
+
+VOID
+NdisWanCopyNdisString(
+ OUT PNDIS_STRING Dest,
+ IN PNDIS_STRING Src
+ );
+
+#ifndef USE_NDIS_MINIPORT_LOCKING
+
+BOOLEAN
+NdisWanAcquireMiniportLock(
+ PADAPTERCB AdapterCB
+ );
+
+VOID
+NdisWanReleaseMiniportLock(
+ PADAPTERCB AdapterCB
+ );
+
+#endif // end of !USE_NDIS_MINIPORT_LOCKING
+
+#endif
+
diff --git a/private/ntos/ndis/ndiswan/wantypes.h b/private/ntos/ndis/ndiswan/wantypes.h
new file mode 100644
index 000000000..ff6750797
--- /dev/null
+++ b/private/ntos/ndis/ndiswan/wantypes.h
@@ -0,0 +1,505 @@
+/*++
+
+Copyright (c) 1990-1995 Microsoft Corporation
+
+Module Name:
+
+ Wantypes.h
+
+Abstract:
+
+ This file contains data structures used by the NdisWan driver
+
+
+
+Author:
+
+ Tony Bell (TonyBe) June 06, 1995
+
+Environment:
+
+ Kernel Mode
+
+Revision History:
+
+ TonyBe 06/06/95 Created
+
+--*/
+
+#ifndef _NDISWAN_TYPES_
+#define _NDISWAN_TYPES_
+
+//
+// OS specific structures
+//
+#ifdef NT
+
+#endif
+//
+// end of OS specific structures
+//
+
+#if DBG
+typedef struct _DBG_SEND_PACKET {
+ LIST_ENTRY Linkage;
+ PVOID Packet;
+ ULONG PacketType;
+ struct _BUNDLECB *BundleCB;
+ ULONG BundleState;
+ ULONG BundleFlags;
+ struct _PROTOCOLCB *ProtocolCB;
+ ULONG ProtocolFlags;
+ struct _LINKCB *LinkCB;
+ ULONG LinkState;
+} DBG_SEND_PACKET, *PDBG_SEND_PACKET;
+
+typedef struct _DBG_SEND_CONTEXT {
+ struct _BUNDLECB *BundleCB;
+ struct _PROTOCOLCB *ProtocolCB;
+ struct _LINKCB *LinkCB;
+ PVOID Packet;
+#define PACKET_TYPE_WAN 1
+#define PACKET_TYPE_NDIS 2
+ ULONG PacketType;
+ PLIST_ENTRY ListHead;
+ PNDIS_SPIN_LOCK ListLock;
+} DBG_SEND_CONTEXT, *PDBG_SEND_CONTEXT;
+
+#endif
+
+typedef struct _WAN_ASYNC_EVENT {
+ LIST_ENTRY Linkage;
+ PVOID Context;
+} WAN_ASYNC_EVENT, *PWAN_ASYNC_EVENT;
+
+//
+// WanRequest structure used to queue requests to the WAN Miniports
+//
+typedef struct _WAN_REQUEST {
+ struct _WAN_REQUEST *pNext; // Next Request on the queue
+ WanRequestType Type; // Sync or Async
+ WanRequestOrigin Origin; // Is this tapi
+ PNDIS_REQUEST pNdisRequest; // Ndis Request type
+ NDIS_STATUS NotificationStatus; // Request status
+ WAN_EVENT NotificationEvent; // Request pending event
+} WAN_REQUEST, *PWAN_REQUEST;
+
+//
+// Used for
+//
+typedef struct _WAN_GLOBAL_LIST {
+ NDIS_SPIN_LOCK Lock; // Access lock
+ ULONG ulCount; // Count of nodes on list
+ ULONG ulMaxCount; // Max allowed on list
+ LIST_ENTRY List; // Doubly-Linked list of nodes
+} WAN_GLOBAL_LIST, *PWAN_GLOBAL_LIST;
+
+//
+// Ethernet Header
+//
+typedef struct _ETH_HEADER {
+ UCHAR DestAddr[6];
+ UCHAR SrcAddr[6];
+ USHORT Type;
+} ETH_HEADER, *PETH_HEADER;
+
+//
+// Receive context for transfer data
+//
+typedef struct _NDISWAN_RECV_CONTEXT {
+ struct _BUNDLECB *BundleCB;
+ struct _PROTOCOLCB *ProtocolCB;
+ PUCHAR WanHeader;
+ ULONG WanHeaderLength;
+ PUCHAR LookAhead;
+ ULONG LookAheadLength;
+ PUCHAR FramePointer;
+ ULONG FrameLength;
+} NDISWAN_RECV_CONTEXT, *PNDISWAN_RECV_CONTEXT;
+
+//
+// The ProtocolType to PPPProtocolID Lookup Table
+//
+typedef struct _PPP_PROTOCOL_TABLE {
+ NDIS_SPIN_LOCK Lock; // Table access lock
+ ULONG ulAllocationSize; // Size of memory allocated
+ ULONG ulArraySize; // MAX size of the two arrays
+ PUSHORT ProtocolID; // Pointer to the ProtocolID array
+ PUSHORT PPPProtocolID; // Pointer to the PPPProtocolID array
+} PPP_PROTOCOL_TABLE, *PPPP_PROTOCOL_TABLE;
+
+//
+// Active connections Table
+//
+typedef struct _CONNECTION_TABLE {
+ NDIS_SPIN_LOCK Lock; // Table access lock
+ ULONG ulAllocationSize; // Size of memory allocated
+ ULONG ulArraySize; // Number of possible connections in table
+ ULONG ulNumActiveLinks; // Number of links in link array
+ ULONG ulNumActiveBundles; // Number of bundles in bundle array
+ LIST_ENTRY BundleList; // List of bundles in table
+ struct _LINKCB **LinkArray; // Pointer to the LinkArray
+ struct _BUNDLECB **BundleArray; // Pointer to the BundleArray
+} CONNECTION_TABLE, *PCONNECTION_TABLE;
+
+typedef struct _IO_DISPATCH_TABLE {
+ ULONG ulFunctionCode;
+ NTSTATUS (*Function)();
+}IO_DISPATCH_TABLE, *PIO_DISPATCH_TABLE;
+
+#ifdef BANDWIDTH_ON_DEMAND
+typedef struct _SEND_SAMPLE {
+ ULONG ulBytesThisSend;
+ ULONG ulReferenceCount;
+ WAN_TIME TimeStamp;
+} SEND_SAMPLE, *PSEND_SAMPLE;
+
+typedef struct _SAMPLE_TABLE {
+ ULONG ulFirstIndex; // Index to first sample in current 1sec period
+ ULONG ulCurrentIndex; // Index to current sample in current 1sec period
+ ULONG ulCurrentSampleByteCount; // Count of bytes sent in this sample period
+ ULONG ulSampleArraySize; // Sample array size
+ WAN_TIME SampleRate; // Time between each sample
+ WAN_TIME SamplePeriod; // Time between 1st sample and last sample
+ SEND_SAMPLE SampleArray[SAMPLE_ARRAY_SIZE]; // SampleArray
+} SAMPLE_TABLE, *PSAMPLE_TABLE;
+#endif
+
+typedef struct _DEFERRED_DESC {
+ struct _DEFERRED_DESC *Next;
+ DeferredType Type;
+ PVOID Context;
+} DEFERRED_DESC, *PDEFERRED_DESC;
+
+typedef struct _DEFERRED_QUEUE {
+ PDEFERRED_DESC Head;
+ PDEFERRED_DESC Tail;
+ ULONG Count;
+ ULONG MaxCount;
+} DEFERRED_QUEUE, *PDEFERRED_QUEUE;
+
+typedef struct _LOOPBACK_DESC {
+ USHORT AllocationSize;
+ USHORT BufferLength;
+ PUCHAR Buffer;
+} LOOPBACK_DESC, *PLOOPBACK_DESC;
+
+typedef struct _RECV_DESC {
+ LIST_ENTRY Linkage;
+ ULONG AllocationSize;
+ ULONG RefCount;
+ struct _BUNDLECB *BundleCB;
+ struct _LINKCB *LinkCB;
+ ULONG SequenceNumber;
+ ULONG Flags;
+ ULONG WanHeaderLength;
+ PUCHAR WanHeader;
+ ULONG LookAheadLength;
+ PUCHAR LookAhead;
+ ULONG CurrentBufferLength;
+ PUCHAR CurrentBuffer;
+ PUCHAR StartBuffer;
+} RECV_DESC, *PRECV_DESC;
+
+typedef struct _HEADER_FIELD_INFO {
+ ULONG Length;
+ PUCHAR Pointer;
+}HEADER_FIELD_INFO, *PHEADER_FIELD_INFO;
+
+typedef struct _HEADER_FRAMING_INFO {
+ ULONG FramingBits; // Framing bits
+ ULONG HeaderLength; // Total length of the header
+#define DO_MULTILINK 0x00000001
+#define DO_COMPRESSION 0x00000002
+#define DO_ENCRYPTION 0x00000004
+#define IO_PROTOCOLID 0x00000008
+#define FIRST_FRAGMENT 0x00000010
+#define DO_FLUSH 0x00000020
+#define DO_LEGACY_ENCRYPTION 0x00000040 // Legacy encryption NT 3.0/3.5/3.51
+#define DO_40_ENCRYPTION 0x00000080 // Pseudo fixed 40 bit encryption NT 4.0
+#define DO_128_ENCRYPTION 0x00000100 // 128 bit encryption NT 4.0 encryption update
+ ULONG Flags; // Framing flags
+ HEADER_FIELD_INFO AddressControl; // Info about the address/control field
+ HEADER_FIELD_INFO Multilink; // Info about the multlink field
+ HEADER_FIELD_INFO Compression; // Info about the compression field
+ HEADER_FIELD_INFO ProtocolID; // Info about the protocol id field
+}HEADER_FRAMING_INFO, *PHEADER_FRAMING_INFO;
+
+//
+// Used in NdisWan for NT 3.5 and NT 3.51 and seemed to work.
+// Made up and tried to not make it a valid memory address.
+//
+#define NDISWAN_MAGIC_NUMBER (ULONG)0xC1207435
+
+typedef struct _WAN_IO_PROTOCOL_RESERVED {
+ ULONG ulMagicNumber;
+ struct _LINKCB *LinkCB;
+ NDIS_HANDLE hPacketPool;
+ PNDIS_PACKET pNdisPacket;
+ NDIS_HANDLE hBufferPool;
+ PNDIS_BUFFER pNdisBuffer;
+ PUCHAR pAllocatedMemory;
+ ULONG ulAllocationSize;
+} WAN_IO_PROTOCOL_RESERVED, *PWAN_IO_PROTOCOL_RESERVED;
+
+typedef struct _NDISWAN_MINIPORT_RESERVED {
+ union {
+
+ struct {
+ PNDIS_PACKET Next; // Pointer to next packet in queue
+ USHORT Reserved; //
+ };
+
+ struct {
+ ULONG MagicNumber; // Used to identify this ndispacket as belonging to ndiswan
+ USHORT ReferenceCount; // Used to count number of fragments this ndispacket
+ };
+ };
+
+ USHORT Flags; // Packet properties
+
+} NDISWAN_MINIPORT_RESERVED, *PNDISWAN_MINIPORT_RESERVED;
+
+//
+// LineUp information that is common to all protocol's
+// routed to the BundleCB
+//
+typedef struct _BUNDLE_LINE_UP {
+ ULONG BundleSpeed; // 100 bps units
+ ULONG ulMaximumTotalSize; // suggested max for send packets
+ NDIS_WAN_QUALITY Quality; //
+ USHORT usSendWindow; // suggested by the MAC
+} BUNDLE_LINE_UP, *PBUNDLE_LINE_UP;
+
+//
+// BundleInfo is information needed by the bundle for framing decisions.
+// This information is the combined information of all links that are part
+// of this bundle.
+//
+typedef struct _BUNDLE_FRAME_INFO {
+ ULONG SendFramingBits; // Send framing bits
+ ULONG RecvFramingBits; // Receive framing bits
+ ULONG MaxRSendFrameSize; // Max size of send frame
+ ULONG MaxRRecvFrameSize; // Max size of receive frame
+} BUNDLE_FRAME_INFO, *PBUNDLE_FRAME_INFO;
+
+#ifdef BANDWIDTH_ON_DEMAND
+typedef struct _BOND_INFO {
+ ULONG ulBytesThreshold; // Threshold in BytesPerSamplePeriod
+ USHORT usPercentBandwidth; // Threshold as % of total bandwidth
+ ULONG ulSecondsInSamplePeriod; // # of seconds in a sample period
+ ULONG State; // Current state
+ WAN_TIME StartTime; // Start time for threshold event
+ SAMPLE_TABLE SampleTable;
+} BOND_INFO, *PBOND_INFO;
+#endif
+
+//
+// This information is used to describe the encryption that is being
+// done on the bundle. At some point this should be moved into
+// wanpub.h and ndiswan.h.
+//
+typedef struct _ENCRYPTION_INFO{
+ UCHAR StartKey[16]; // Start key
+ UCHAR SessionKey[16]; // Session key used for encrypting
+ ULONG SessionKeyLength; // Session key length
+ PVOID Context; // Key encryption context
+} ENCRYPTION_INFO, *PENCRYPTION_INFO;
+
+//
+// This is the control block that defines a bundle (connection). This block is created when
+// a WAN Miniport driver gives a lineup indicating a new connection has been established.
+// This control block will live as long as the connection is up (until a linedown is received) or
+// until the link associated with the bundle is added to a different bundle. BundleCB's live in
+// the global bundle array with their hBundleHandle as their index into the array.
+//
+typedef struct _BUNDLECB {
+ LIST_ENTRY Linkage; // Linkage for the global free list
+ NDIS_HANDLE hBundleHandle; // Index of this bundle in bundle array
+ NDIS_HANDLE hBundleContext; // Context passed down by usermode
+ ULONG ulAllocationSize; // Size of memory allocated
+ ULONG ulReferenceCount; // Reference count for this structure
+ BundleState State;
+ NDIS_SPIN_LOCK Lock; // Structure access lock
+
+ LIST_ENTRY LinkCBList; // List head for links in this bundle
+ ULONG ulLinkCBCount; // Count of links in the bundle
+
+ BUNDLE_FRAME_INFO FramingInfo; // Framing information for this bundle
+
+ //
+ // Send section
+ //
+ struct _LINKCB *NextLinkToXmit; // Next link to send data over
+ ULONG SendingLinks; // Number of links with wanpacket count > 1
+ LIST_ENTRY SendPacketQueue; // List head of wanpackets waiting to be sent
+ ULONG SendSeqNumber; // Current send sequence number (multilink)
+ ULONG SendSeqMask; // Mask for send sequence numbers
+ ULONG SendSeqTest; // Test for sequence number diff
+
+#define IN_SEND 0x00000001
+#define IN_RECEIVE 0x00000002
+#define TRY_SEND_AGAIN 0x00000004
+#define RECV_PACKET_FLUSH 0x00000008
+#define PROTOCOL_PRIORITY 0x00000010
+#define FRAMES_PENDING 0x00000020
+#define BUNDLE_ROUTED 0x00000040
+#define INDICATION_EVENT 0x00000080
+ ULONG Flags; // Flags
+
+ ULONG OutstandingFrames; // Number of outstanding sends on this bundle
+ WAN_EVENT OutstandingFramesEvent; // Async notification event for pending sends
+ NDIS_STATUS IndicationStatus;
+ WAN_EVENT IndicationEvent;
+
+ //
+ // Receive section
+ //
+ LIST_ENTRY RecvDescPool; // List of available recv desc's
+ ULONG RecvDescCount; // Count of available recv desc's
+ ULONG RecvDescMax; // Max number recv desc's needed
+ LIST_ENTRY RecvDescAssemblyList; // List head for assembly of recv descriptors
+ PRECV_DESC RecvDescHole; // Pointer to 1st hole in recv desc list
+ ULONG HoleSeqNumber; // Sequence number of the hole
+ ULONG MinReceivedSeqNumber; // Minimum recv sequence number on the bundle
+ ULONG RecvSeqMask; // Mask for receive sequence number
+ ULONG RecvSeqTest; // Test for sequence number diff
+ ULONG RecvFragmentsLost; // Count of recv fragments flushed
+ WAN_TIME LastRecvNonIdleData;
+
+ //
+ // Protocol information
+ //
+ struct _PROTOCOLCB **ProtocolCBTable; // Pointer to table of pointers to protocolcb's
+ ULONG ulNumberOfRoutes; // Number of protocolcb's in protocol table
+ LIST_ENTRY ProtocolCBList; // List head for protocols routed to this bundle
+ ULONG SendMask; // Send Mask for all send queues
+ BUNDLE_LINE_UP LineUpInfo; // Lineup info common to all protocols
+
+ //
+ // VJ information
+ //
+ VJ_INFO SendVJInfo; // Send VJ compression options
+ VJ_INFO RecvVJInfo; // Recv VJ compression options
+ struct slcompress *VJCompress; // Pointer to VJ compression table
+
+ //
+ // MS Compression
+ //
+ COMPRESS_INFO SendCompInfo; // Send compression options
+ PVOID SendCompressContext; // Pointer to send compressor context
+
+ COMPRESS_INFO RecvCompInfo; // Recv compression options
+ PVOID RecvCompressContext; // Pointer to receive decompressor context
+
+ //
+ // MS Encryption
+ //
+ ENCRYPTION_INFO SendEncryptInfo;
+ PVOID SendRC4Key; // Pointer to send encryption context
+
+ ENCRYPTION_INFO RecvEncryptInfo;
+ PVOID RecvRC4Key; // Pointer to receive encryption context
+
+ USHORT SCoherencyCounter; // Coherency counters
+ USHORT RCoherencyCounter; //
+ USHORT LastRC4Reset; // Encryption key reset
+ UCHAR CCPIdentifier; //
+
+#ifdef BANDWIDTH_ON_DEMAND
+ //
+ // Bandwidth on Demand
+ //
+ BOND_INFO UpperBonDInfo;
+ BOND_INFO LowerBonDInfo;
+#endif
+
+ //
+ // Bundle Name
+ //
+ ULONG ulNameLength; // Bundle name length
+ UCHAR Name[MAX_NAME_LENGTH]; // Bundle name
+
+ //
+ // Bundle statistics
+ //
+ WAN_STATS BundleStats; // Bundle statistics
+
+} BUNDLECB, *PBUNDLECB;
+
+
+//
+// This control blocks defines an active link that is part of a bundle (connection). This block
+// is created when a WAN Miniport driver gives a lineup indicating that a new connection has been
+// established. The control block lives until a linedown indication is received for the link.
+// The control block lives linked into a bundle control block.
+//
+typedef struct _LINKCB {
+ LIST_ENTRY Linkage; // Used to link the link into a bundle
+ NDIS_HANDLE hLinkHandle; // Index of this link in the active link array
+ NDIS_HANDLE hLinkContext; // Context passed down by usermode
+ ULONG ulAllocationSize; // Size of memory allocated
+ ULONG ulReferenceCount; // Reference count
+ LinkState State;
+ struct _WAN_ADAPTERCB *WanAdapterCB; // WanAdapter Context for this link
+ struct _BUNDLECB *BundleCB; // Pointer to owning bundle control block
+ NDIS_HANDLE NdisLinkHandle; // Handle given at lineup by the miniport
+
+ PUCHAR PacketMemory; // Pointer to packet memory allocation
+ ULONG PacketMemorySize; // Size of packet memory allocation
+ ULONG BufferSize; // Size of buffer in each packet
+ LIST_ENTRY WanPacketPool; // Pool of NDIS_WAN_PACKETS
+ ULONG ulWanPacketCount; // Count of available packets
+ ULONG PPPHeaderLength; // Length of the PPP header for this link
+ ULONG LastRecvSeqNumber; // Last recv sequence number on this link
+ ULONG RecvFragmentsLost; // Number of lost fragments on this link
+
+ ULONG OutstandingFrames; // Number of outstanding frames on the link
+ WAN_EVENT OutstandingFramesEvent; // Async notification event for pending sends
+ ULONG ulBandwidth; // % of the bundle bandwidth that this link has
+
+ WAN_LINK_INFO LinkInfo; // Framing information for this link
+ NDIS_MAC_LINE_UP LineUpInfo; // Link specific lineup information
+
+
+ ULONG ulNameLength; // Name length
+ UCHAR Name[MAX_NAME_LENGTH]; // Name of the link
+
+ WAN_STATS LinkStats; // Link statistics
+} LINKCB, *PLINKCB;
+
+//
+// The protocol control block defines a protocol that is routed to a bundle
+//
+typedef struct _PROTOCOLCB {
+ LIST_ENTRY Linkage; // Used to link the protocolcb onto the bundle
+ NDIS_HANDLE hProtocolHandle; // Index of this protocol in the bundle protocol array
+ ULONG ulAllocationSize; // Size of memory allocated
+ ULONG ulReferenceCount; // References to this structure
+#define PROTOCOL_ROUTED 0x00000001
+ ULONG Flags;
+ PNDIS_PACKET HeadNdisPacketQueue; // Queue of NdisPackets waiting to be sent
+ PNDIS_PACKET TailNdisPacketQueue; // Last packet on the queue
+ ULONG SendMaskBit; // Send mask bit for this protocol send queue
+ struct _ADAPTERCB *AdapterCB; // Pointer to the adaptercb
+ struct _BUNDLECB *BundleCB; // Pointer to the bundlecb
+ USHORT usProtocolType; // EtherType of this protocol
+ USHORT usPPPProtocolID; // PPP Protocol ID
+ WAN_TIME LastRecvNonIdleData; // Time at which last non-idle packet was recv'd
+ BOOLEAN (*NonIdleDetectFunc)(); // Function to sniff for non-idle data
+#ifdef BANDWIDTH_ON_DEMAND
+ USHORT usPriority; // Protocol's priority setting
+ ULONG ulByteQuota; // Number of bytes allowed to be sent in 1sec
+ SAMPLE_TABLE SampleTable; // Sample table
+#endif
+ NDIS_HANDLE hTransportHandle; // Transport's connection identifier
+ UCHAR NdisWanAddress[6]; // MAC address used for this protocol
+ UCHAR TransportAddress[6]; // MAC address used for indications to transport
+ NDIS_STRING BindingName;
+ NDIS_STRING DeviceName;
+ ULONG ulLineUpInfoLength; // Length of protocol specific lineup info
+ PUCHAR LineUpInfo; // Pointer to protocol specific lineup info
+} PROTOCOLCB, *PPROTOCOLCB;
+
+#endif // WAN_TYPES
+