diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/ntos/ndis/ndiswan | |
download | NT4.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')
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 + |