|
|
// Copyright (c) 1997, Microsoft Corporation, all rights reserved
//
// l2tpp.h
// RAS L2TP WAN mini-port/call-manager driver
// Main private header (precompiled)
//
// 01/07/97 Steve Cobb
//
//
// About naming:
//
// This driver contains code for both the L2TP mini-port and the L2TP call
// manager. All handler routines exported to NDIS are prefixed with either
// 'Lmp' for the mini-port handlers or 'Lcm' for the call manager handlers.
//
//
// About locks:
//
// Data structures that may change during simultaneous requests to different
// processors in a multi-processor system must be protected with spin-locks or
// accessed only with interlocked routines. Where locking is required to
// access a data field in this header, the comment for that field indicates
// same. A CoNDIS client is a trusted kernel mode component and presumed to
// follow the documented call sequences of CoNDIS. Some access conflicts that
// might be caused by goofy clients are not checked, though the easy ones are.
// Cases where multiple clients might conflict are protected even though, for
// now, the TAPI proxy is expected to be the only client.
//
//
// About TDI and NDIS compliance:
//
// This driver is generally compliant with documented TDI and NDIS procedures,
// but there are two compliance issues worth mentioning. First, it takes
// performance advantage from the fact that NDIS_BUFFERs and TDI I/O buffers
// are both defined as MDLs (see NDISBUFFERISMDL in tdix.c). Second, it is
// built by default to take advantage of an IRP handling optimization which
// may be non-TDI-compliant though the docs are not real clear on the point
// (see ALLOCATEIRPS in tdix.c). The driver could be made fully compliant on
// the first point in one hour and on the second by changing a #if
// option...but there would be a performance penalty. Finally,
// InterlockedExchangePointer and InterlockedCompareExchangePointer are used,
// though there don't currently appear to be any NDIS equivalents.
#ifndef _L2TPP_H_
#define _L2TPP_H_
// If set, less commom allocations such as 1-per-call control blocks are made
// from lookaside lists. Otherwise they are made using heap calls. This
// option makes sense where a large number of calls are expected to be
// handled.
//
#define LLISTALL 0
// If set, ReadFlags translates into a simple assigment, otherwise it is an
// Interlocked operation. Set this to 1 if a bus read of ULONG size is
// atomic.
//
#define READFLAGSDIRECT 1
#include <ntddk.h>
#include <tdi.h>
#include <tdikrnl.h>
#include <tdiinfo.h>
#include <ntddtcp.h>
#include <ntddip.h>
#include <ntddndis.h>
#include <ipinfo.h>
#include <tcpinfo.h>
#include <ndis.h>
#include <ndiswan.h>
#include <ndistapi.h>
#include <ntverp.h>
//#include <ndisadd.h> // Temporary
#include <md5.h>
#include <bpool.h>
#include <ppool.h>
#include <timer.h>
#include <debug.h>
#include <tdix.h>
#include <l2tp.h>
#include <l2tprfc.h>
//-----------------------------------------------------------------------------
// Constants
//-----------------------------------------------------------------------------
// The NDIS version we report when registering mini-port and address family.
//
#define NDIS_MajorVersion 5
#define NDIS_MinorVersion 0
// Size of an IPv4 header. Because the RawIp driver returns the IP header on
// received datagrams, this must be added onto the allocated buffer size. We
// assume there will be no rarely used IP-option fields on L2TP traffic.
//
// Note: Suggested to PradeepB that RawIp should strip the IP header, and he
// is considering adding an open-address option. This can be removed if
// said option materializes.
//
#define IpFixedHeaderSize 20
// UDP header size
#define UDP_HEADER_SIZE 8
// The maximum number of bytes in a frame including the largest L2TP payload
// header, plus the 32 bytes the OID_WAN_GET_INFO documentation says should be
// reserved internally for "bridging and additional protocols". This value is
// used for receive buffer allocations internally. The L2TP draft/RFC
// guarantees that control messages will fit in L2TP_MaxFrameSize, so a buffer
// of this size is capable of receiving either payload or control packets.
//
#define L2TP_FrameBufferSize (L2TP_MaxFrameSize + L2TP_MaxPayloadHeader + 32)
// The maximum number of bytes in an L2TP control or payload header. This
// value is used for buffer allocations internally.
//
#define L2TP_HeaderBufferSize L2TP_MaxHeaderSize + IpFixedHeaderSize + UDP_HEADER_SIZE
// Reported speed of a LAN tunnel in bits/second.
//
#define L2TP_LanBps 10000000
// The vendor name passed to peer during tunnel creation.
//
#define L2TP_VendorName "Microsoft"
// The firmware/software revision passed to peer during tunnel creation. The
// value indicates "NT 5.0".
//
#define L2TP_FirmwareRevision VER_PRODUCTVERSION_W
// The maximum length of an IP address string of the form "a.b.c.d".
//
#define L2TP_MaxDottedIpLen 15
// Milliseconds in a Hello timer interval. Not to be confused with the Hello
// timeout which is generally much longer than this. See '*Hello*' fields in
// the TUNNELCB.
//
#define L2TP_HelloIntervalMs 10000
//-----------------------------------------------------------------------------
// Data types
//-----------------------------------------------------------------------------
// Forward declarations.
//
typedef struct _VCCB VCCB; typedef struct _INCALLSETUP INCALLSETUP; typedef struct _TUNNELWORK TUNNELWORK;
// Adapter control block defining the state of a single L2TP mini-port
// adapter. An adapter commonly supports multiple VPN devices. Adapter
// blocks are allocated in MiniportInitialize and deallocated in MiniportHalt.
//
typedef struct _ADAPTERCB { // Set to MTAG_ADAPTERCB for easy identification in memory dumps and use
// in assertions.
//
ULONG ulTag;
// Reference count on this control block. The reference pairs are:
//
// (a) A reference is added when the MiniportAdapterHandle field is set,
// i.e. when LmpInitialize succeeds and cleared when the LmpHalt
// handler is called. The adapter block is actually passed to NDIS
// before it's known if LmpInitialize will succeed but according to
// ArvindM NDIS will not call halt unless it succeeds.
//
// (b) A reference is added when the NdisAfHandle field is set and removed
// when it is cleared.
//
// (c) A reference is added when the NdisSapHandle field is set and
// removed when it is cleared.
//
// (d) A reference is added for the VCCB's back pointer and removed when
// the VCCB is freed.
//
// (e) A reference is added for the TUNNELCB's back pointer and removed
// when the TUNNELCB is freed.
//
// (f) A reference is added when an NDIS_WORK_ITEM is scheduled and
// removed when it has completed.
//
// Access is via ReferenceAdapter and DereferenceAdapter only.
//
LONG lRef;
// ACBF_* bit flags indicating various options. Access restrictions are
// indicated for each individual flag. Many of these flags are set
// permanently at initialization and so have no access limitation.
//
// ACBF_OutgoingRoleLac: Set when the driver is to assume the role of the
// L2TP Access Concentrator (LAC) as opposed to the L2TP Network
// Server (LNS) when making outgoing calls. It would be simple to act
// either as LAC or LNS based on a CALL_PARAMETER field, if necessary,
// though this is not currently implemented.
//
// ACBF_IgnoreFramingMismatch: Set when a received framing type bit of
// "asynchronous" is to be ignored, rather than failing the
// negotiation. This is a hedge against buggy peers as there are late
// draft changes to the order of the framing type bits.
//
// ACBF_ExclusiveTunnels: Set when an exclusive tunnel is to be created to
// the peer for each outgoing call even if another tunnel already
// exists to the peer. This is a default and may be overridden in the
// L2TP specific call parameters.
//
// ACBF_SapActive: Set when the TDI open associated with the NdisSapHandle
// is successful and cleared when the corresponding TDI close is
// scheduled. Access is protected by 'lockSap'.
//
ULONG ulFlags; #define ACBF_OutgoingRoleLac 0x00000001
#define ACBF_IgnoreFramingMismatch 0x00000002
#define ACBF_ExclusiveTunnels 0x00000004
#define ACBF_SapActive 0x00000010
// The maximum number of out-of-order packets that may be queued on any
// tunnel or link. The value is read from the registry. The value 0
// effectively disables out-of-order handling.
//
SHORT sMaxOutOfOrder;
// The maximum receive window we send to peer during tunnel setup for the
// control session. The value is read from the registry. The value 0
// means the Receive Window Size AVP should not be sent, though for
// control this just results in peer using a default of 4.
//
USHORT usControlReceiveWindow;
// The maximum receive window we send to peer during call setup for the
// payload session. The value is read from the registry. The value 0
// means the Receive Window Size AVP should not be sent, which results in
// no sequence/acknowledge numbers being used for calls we initiate. Note
// that on peer originatated calls where peer specifies a window, 0 will
// result in the default of 4 being offered.
//
USHORT usPayloadReceiveWindow;
// The Hello timeout in milliseconds, i.e. the time that must elapse from
// the last incoming packet before a "Hello" message is sent to verify the
// media is still up. The value is read from the registry. A value of 0
// effectively disables the Hello mechanism.
//
ULONG ulHelloMs;
// The maximum milliseconds to wait for an acknowledge after sending a
// control or payload packet. The value is read from the registry.
//
ULONG ulMaxSendTimeoutMs;
// The initial milliseconds to wait for an acknowledge after sending a
// control or payload packet. The send timeout is adaptive, so this value
// is the seed only. The value is read from the registry.
//
ULONG ulInitialSendTimeoutMs;
// The maximum milliseconds to wait for an outgoing packet on which to
// piggyback an acknowledge before sending a zero data acknowledge. If
// the value is greater than 1/4 of the current send timeout, the former
// is used, i.e. this is the "maximum adaptive maximum".
//
ULONG ulMaxAckDelayMs;
// The maximum number of times a control packet is retransmitted before
// the owning tunnel is reset. The value is read from the registry.
//
ULONG ulMaxRetransmits;
// The randomly unique tie-breaker AVP value sent with all SCCRQ messages.
// This field is currently unused. After due consideration, I have
// decided not to send tie-breaker AVPs in our SCCRQs. The mechanism is
// way too complicated for a rare case. If peer really doesn't want two
// tunnels he will simply ignore ours and let it timeout and fail anyway.
// This is a minor, and I believe harmless, incompliance with the
// draft/RFC. My guess is that others will reach this same conclusion and
// not send tie-breakers either.
//
CHAR achTieBreaker[ 8 ];
// The password shared with peer for tunnel identification. The value is
// read from the registry. Currently, only a single password for all
// peers is used, though a password indexed by 'hostname' will likely be
// added in the future.
//
CHAR* pszPassword;
// The driver description read from the registry. The value is used as
// the L2TP line name when reporting up capabilities.
//
WCHAR* pszDriverDesc;
// Our framing and bearer capablities bit masks as passed in SCCRQ.
//
ULONG ulFramingCaps; ULONG ulBearerCaps;
// The string sent as the host name, or NULL if none. The value is read
// from the registry.
//
CHAR* pszHostName;
// The next progressively increasing reference number likely to be unique
// for all interconnected LACs/LNSs for a significant period of time. It
// is for use by administrators on either end of the tunnel to use when
// investigating call failure problems. Access is via Interlocked
// routines.
//
ULONG ulCallSerialNumber;
// VC TABLE --------------------------------------------------------------
// The array of VC control block addresses allocated during adapter
// initialization. The VC control blocks themselves are created and hung
// off this table dynamically. Our Call-ID context returned to us by peer
// in each L2TP packet is a 1-based index into this table. (The 0 Call-ID
// is reserved by L2TP to mean "not call specific").
//
// If an element is NULL, it means the Call-ID is not in use. If an
// element is -1, it means the Call-ID has been reserved, but messages
// with the Call-ID are not yet acceptable. Any other value is the
// address of a VCCB for which messages can be accepted. 'VCCB.pTunnel'
// is guaranteed valid while a VCCB is in the array.
//
// Access to the array is protected by 'lockVcs'.
//
VCCB** ppVcs;
// The number of elements in the 'ppVcs' array. This corresponds to the
// number of configured VPN devices read from the registry during
// initialization.
//
USHORT usMaxVcs;
// Number of slots in 'usMaxVcs' that are available, i.e. NULL. Access is
// protected by 'lockVcs'
//
LONG lAvailableVcSlots;
// Lock protecting the VC table, "available" counter, and 'listVcs'.
//
NDIS_SPIN_LOCK lockVcs;
// The next Call-ID above 'usMaxVcs' for use only in terminating a call
// gracefully. Access is by the GetNextTerminationCallId routine only.
//
USHORT usNextTerminationCallId;
// TUNNEL CHAIN ----------------------------------------------------------
// Head of a double-linked list of active TUNNELCBs. At no time will two
// tunnels in the list have the same 'TUNNELCB.usTunnelId' or same
// 'TUNNELCB.ulIpAddress'/'TUNNELCB.usAssignedTunnelId' pair. Access to
// the list links is protected by 'lockTunnels'.
//
LIST_ENTRY listTunnels; NDIS_SPIN_LOCK lockTunnels;
// The tunnel identifier to assign to the next tunnel created. Only the
// GetNextTunnelId routine should access this field.
//
USHORT usNextTunnelId;
// TDI -------------------------------------------------------------------
// TDI extension context containing TDI state information for the adapter.
// Access is via Tdix* interface routines, which handle all locking
// internally.
//
TDIXCONTEXT tdix;
// NDIS BOOKKEEPING ------------------------------------------------------
// NDIS's handle for this mini-port adapter passed to us in
// MiniportInitialize. This is passed back to various NdisXxx calls.
//
NDIS_HANDLE MiniportAdapterHandle;
// NDIS's handle for our SAP as passed to our CmRegisterSapHandler or NULL
// if none. Only one SAP handle is supported because (a) the TAPI proxy's
// is expected to be the only one, and (b) there are no L2TP SAP
// properties that would ever lead us to direct a call to a second SAP
// anyway. Any client's attempt to register a second SAP will fail. A
// value of NULL indicates no SAP handle is currently registered. Writers
// must hold 'lockSap'. Readers must hold 'lockSap' or a SAP reference.
//
NDIS_HANDLE NdisSapHandle;
// Line and address IDs assigned by NDIS to the active SAP.
//
ULONG ulSapLineId; ULONG ulSapAddressId;
// NDIS's handle for our Address Family as passed to our CmOpenAfHandler
// or NULL if none. Only one is supported. See NdisSapHandle above.
// Access is via Interlocked routines.
//
NDIS_HANDLE NdisAfHandle;
// This adapter's capabilities as returned to callers on
// OID_WAN_CO_GET_INFO. These capabilities are also used as defaults for
// the corresponding VCCB.linkinfo settings during MiniportCoCreateVc.
//
NDIS_WAN_CO_INFO info;
// Reference count on the NdisAfHandle. The reference pairs are:
//
// (a) A reference is added when the address family is opened and removed
// when it is closed.
//
// (b) A reference is added when a SAP is registered on the address family
// and removed when it is deregistered.
//
// (c) A reference is added when a VC is created on the address family and
// removed when it is deleted.
//
// Access is via ReferenceAf and DereferenceAf only.
//
LONG lAfRef;
// Reference count on the NdisSapHandle. The reference pairs are:
//
// (a) A reference is added when the SAP is registered and removed when it
// is de-registered.
//
// (b) A reference is added and immediately removed in FsmTunnelIdle to
// test for an active SAP in order to immediately reject requested
// tunnels when no SAP is active.
//
// (c) A reference is added when before calling
// NdisMCmDispatchIncomingCall and removed when the call returns.
//
// Access is via ReferenceSap and DereferenceSap only, excepting initial
// reference by RegisterSapPassive. Access is protected by 'lockSap'.
//
LONG lSapRef;
// This lock protects the 'lSapRef' and 'NdisSapHandle' fields.
//
NDIS_SPIN_LOCK lockSap;
// RESOURCE POOLS --------------------------------------------------------
// Count of initialized but not yet completed timers. We cannot allow a
// Halt to complete until this goes to 0, because if we did our driver
// could be unloaded with running timers in our memory which results in a
// bugcheck.
//
ULONG ulTimers;
// Pool of full frame buffers with pre-attached NDIS_BUFFER descriptors.
// The pool is accessed via the interface defined in bpool.h, which
// handles all locking internally.
//
BUFFERPOOL poolFrameBuffers;
// Pool of L2TP header buffers with pre-attached NDIS_BUFFER descriptors.
// The pool is accessed via the interface defined in bpool.h, which
// handles all locking internally.
//
BUFFERPOOL poolHeaderBuffers;
// Pool of NDIS_PACKET descriptors used in indication of received frames.
// The pool is accessed via the interface defined in ppool.h, which
// handles all locking internally.
//
PACKETPOOL poolPackets;
// Lookaside list of NDIS_WORK_ITEM scheduling descriptors with extra
// context space used by all tunnels and VCs attached to the adapter.
//
NPAGED_LOOKASIDE_LIST llistWorkItems;
// Lookaside list of TIMERQITEM timer event descriptors used by all
// tunnels and VCs attached to the adapter.
//
NPAGED_LOOKASIDE_LIST llistTimerQItems;
// Lookaside list of CONTROLSENT sent control packet contexts used by all
// tunnels attached to the adapter.
//
NPAGED_LOOKASIDE_LIST llistControlSents;
// Lookaside list of PAYLOADLSENT sent payload packet contexts used by all
// VCs attached to the adapter.
//
NPAGED_LOOKASIDE_LIST llistPayloadSents;
// Lookaside list of TUNNELWORK incoming VC setup contexts used for all
// tunnels attached to the adapter.
//
NPAGED_LOOKASIDE_LIST llistTunnelWorks;
// Lookaside list of CONTROLMSGINFO contexts used for all tunnels and VCs
// attached to the adapter.
//
NPAGED_LOOKASIDE_LIST llistControlMsgInfos;
#if LLISTALL
// Lookaside list of TUNNELCBs from which the 'listTunnels' control blocks
// are allocated.
//
NPAGED_LOOKASIDE_LIST llistTunnels;
// Lookaside list of VCCBs from which the control blocks dynamically
// attached to '*ppVcs' are allocated.
//
NPAGED_LOOKASIDE_LIST llistVcs;
// Lookaside list of TIMERQ descriptors used by all tunnels attached to
// the adapter.
//
NPAGED_LOOKASIDE_LIST llistTimerQs;
// Lookaside list of CONTROLRECEIVED received control packet contexts used
// by all tunnels attached to the adapter.
//
NPAGED_LOOKASIDE_LIST llistControlReceiveds;
// Lookaside list of PAYLOADRECEIVED received payload packet contexts used
// by all VCs attached to the adapter.
//
NPAGED_LOOKASIDE_LIST llistPayloadReceiveds;
// Lookaside list of CALLSETUP incoming VC setup contexts used for all
// incoming VCs attached to the adapter.
//
NPAGED_LOOKASIDE_LIST llistInCallSetups; #endif
} ADAPTERCB;
// Tunnel control block, describing the state of an L2TP tunnel, i.e. an L2TP
// control channel session to another L2TP LNS or LAC. Each tunnel may have
// zero or more VCs associated with it. Tunnel control blocks are allocated
// from 'ADAPTERCB.llistTunnels' in CmMakeCall and ReceiveControl. Blocks are
// deallocated when the last reference is removed, e.g. when the control
// connection FSM terminates the tunnel.
//
typedef struct _TUNNELCB { // Links to the prev/next TUNNELCB in the owning adapter's tunnel list.
// Access to the list links is protected by 'ADAPTERCB.lockTunnels'.
//
LIST_ENTRY linkTunnels;
// Set to MTAG_TUNNELCB for easy identification in memory dumps and use in
// assertions.
//
ULONG ulTag;
// Reference count on this control block. The reference pairs are:
//
// (a) A reference is added when a call on a VCCB is active or becoming
// active and removed when it is deactivated, i.e. during the period
// the VCCB is on 'listVcs'. This covers the back pointer in the
// VCCB.
//
// (b) A reference is added when peer initiates a tunnel and removed when
// the tunnel transitions to idle state. This keeps peer-initiated
// tunnels from terminating when there are no no calls, since by
// convention, it is peer who closes the tunnel in that case.
//
// (c) A reference is added when a graceful tunnel close is initiated and
// removed when the tunnel transitions to idle state.
//
// (d) A reference is added when the delayed control acknowledge timer is
// scheduled and removed by the timer event handler.
//
// (e) LookUpTunnelAndVcCbs adds a reference that is removed at the end of
// the L2tpReceive handler. This covers the receive path.
//
// (f) A reference is added when a CONTROLSENT context is assigned a
// tunnel back pointer and removed when the context is freed.
//
// (g) A reference is added when a PAYLOADSENT context is assigned a
// tunnel back pointer and removed when the context is freed.
//
// (h) ScheduleTunnelWork adds a reference that is removed by TunnelWork
// after executing the work. This covers the tunnel pointer passed as
// a context to NdisScheduleWorkItem.
//
// Access is via ReferenceTunnel and DereferenceTunnel only which use
// 'ADAPTERCB.lockTunnels' for protection.
//
LONG lRef;
// Back pointer to owning adapter's control block.
//
ADAPTERCB* pAdapter;
// This lock protects TUNNELCB send, receive, and state fields as noted in
// other field descriptions.
//
NDIS_SPIN_LOCK lockT;
// TUNNEL SETUP ----------------------------------------------------------
// IP address and UDP port of the remote end of the tunnel in network byte
// order. The IP address is pulled from the call parameters passed to
// CmMakeCall. It is updated with the last source IP address received
// from a peer passing this tunnel's ID, per the L2TP draft/RFC section
// 8.1 on "L2TP over IP/UDP media". However, it is assumed that the
// updated source address will not match the address of another existing
// tunnel. The UDP port (not used in raw IP mode) is initially the well
// known L2TP port (1701). It is updated with the last source UDP port
// received from peer on this tunnel. Access is protected by
// 'pAdapter->lockTunnels'.
//
TDIXIPADDRESS address;
// IP address and ifindex of my end of the tunnel in network byte
// used to get the media speed and build IP header
TDIXIPADDRESS localaddress;
TDIXUDPCONNECTCONTEXT udpContext;
// "Connection" cookie returned by TdixAddHostRoute. This may be passed
// to TdixSendDatagram to send on the connected channel (used for sent
// payloads) as opposed to the unconnected channel (used for receives and
// sent controls). The address is invalid after TdixDeleteHostRoute is
// called.
//
TDIXROUTE* pRoute;
// Our unique tunnel identifier sent back to us by peer in the L2TP
// header. The value is chosen, using GetNextTunnelId, from a sequential
// counter in ADAPTERCB and has no further meaning.
//
USHORT usTunnelId;
// The tunnel identifier chosen by peer that we send back to him in the
// L2TP header Tunnel-ID field for all packets on this tunnel. A value of
// 0 indicates no ID has been assigned.
//
USHORT usAssignedTunnelId;
// TCBF_* bit flags indicating various options and states. Access is via
// the interlocked ReadFlags/SetFlags/ClearFlags routines only.
//
// TCBF_TdixReferenced: Set when the tunnel has referenced the adapter's
// TDI extension context by successfully calling TdixOpen.
// DereferenceTunnel uses this to automatically dereference the
// context when the tunnel is dereferenced.
//
// TCBF_CcInTransition: Set when the control connection FSM has begun but
// not finished a sequence of state changes that will end up in either
// Idle or Established state. When this flag is set new requests to
// bring the tunnel up or down are queued on 'listRequestingVcs' for
// re-execution when a result is known. Access to the bit is
// protected by 'lockT'.
//
// TCBF_PeerInitiated: Set when the tunnel was initiated by the peer,
// rather than a local request. If all calls are dropped and this bit
// is not set, we close the tunnel gracefully.
//
// TCBF_PeerInitRef: Set when a reference for peer initation is taken on
// the tunnel and cleared when the reference is removed.
//
// TCBF_HostRouteAdded: Set when the host route is successfully added and
// referenced and removed when it is dereferenced.
//
// TCBF_HostRouteChanged: Set when a host route changed has been attempted
// on the tunnel, and never cleared.
//
// TCBF_PeerNotResponding: Set when the tunnel is closed due to lack of
// response from peer, i.e. after all retries have been exhausted.
//
// TCBF_Closing: Set as soon as the tunnel is known to be transitioning to
// idle state. Access is protected by 'lockT'.
//
// TCBF_FsmCloseRef: Set when a graceful closing exchange is initiated by
// FsmClose and cleared when the tunnel reaches idle state.
//
// TCBF_InWork: Set when an APC is scheduled to execute work from the
// 'listWork' queue. Access is protected by 'lockWork'.
//
ULONG ulFlags; #define TCBF_TdixReferenced 0x00000001
#define TCBF_CcInTransition 0x00000002
#define TCBF_PeerInitiated 0x00000004
#define TCBF_PeerInitRef 0x00000008
#define TCBF_HostRouteAdded 0x00000010
#define TCBF_PeerNotResponding 0x00000020
#define TCBF_HostRouteChanged 0x00000040
#define TCBF_Closing 0x00000100
#define TCBF_FsmCloseRef 0x00000200
#define TCBF_InWork 0x00001000
#define TCBF_SendConnected 0x00002000
#define TCBF_LocalAddrSet 0x00004000
// The current state of the tunnel's control connection creation FSM. See
// also 'VCCB.state'.
//
// Only one tunnel creation session may be underway even if CmMakeCall has
// been called on multiple VCs over this tunnel. For this reason,
// transitions to/from the Idle or Established states must be protected by
// 'lockT'. See also TCBF_CcInTransition flag and 'listRequestingVcs'.
//
// The protocol sorts out the case of simultaneous originate and receive
// requests ensuring that one gets dropped before it reaches Established
// state when either provides a tie-breaker. We always provide a
// tie-breaker for IP media. For QOS-enabled medias where one control
// channel per call makes sense and no tie-breakers are passed, a lower
// level VC ID will be used to distinguish tunnel control blocks on
// receive. So, a single TUNNELCB will never have both originated and
// received control channels in Established state.
//
L2TPCCSTATE state;
// Double-linked queue of all VCCBs waiting for the tunnel to open. New
// VCs must not be linked on closing tunnels, i.e. those with the
// TCBF_Closing flag set. Access is protected by 'lockT'.
//
LIST_ENTRY listRequestingVcs;
// Double-linked queue of VCCBs whose VCBF_XxxPending operation has
// completed. 'VCCB.status' is the status that will be indicated. This
// mechanism is necessary to avoid the spin-lock issues that results when
// one tries to call NDIS completion APIs from the bowels of the FSMs.
//
LIST_ENTRY listCompletingVcs; // Peer's framing and bearer capablities.
//
ULONG ulFramingCaps; ULONG ulBearerCaps;
// The challenge and challenge response sent to peer. These are in the
// control block for convenience, as they must be passed thru the work
// scheduling mechanism and don't fit easily into the generic arguments.
//
CHAR achChallengeToSend[ 16 ]; CHAR achResponseToSend[ 16 ];
// SEND STATE ------------------------------------------------------------
// Next Sent, the sequence number of next control packet transmitted on
// this tunnel. The field is initialized to 0 and incremented after
// assignment to an outgoing packet, excepting retransmissions. Access is
// protected by 'lockT'.
//
USHORT usNs;
// Double-linked list of outstanding sends, i.e. CONTROLSENTs sorted by
// the 'usNs' field with lower values near the head. The list contains
// all active unacknowledged CONTROLSENT contexts, even those that may be
// waiting for their first transmission. Access is protected by 'lockT'.
//
LIST_ENTRY listSendsOut;
// The number of control packets sent but not acknowledged or timed out.
// Access is protected by 'lockT'.
//
ULONG ulSendsOut;
// The number of sent but unacknowledged packets that may be outstanding.
// This value is adjusted dynamically. Per the draft/RFC, when
// 'ulAcksSinceSendTimeout' reaches the current setting, the window is
// increased by one. When a send timeout expires the window is reduced by
// half. Access is protected by 'lockT'.
//
ULONG ulSendWindow;
// The maximum value of 'ulSendWindow'. Peer chooses this value during
// call setup by offering a receive window.
//
ULONG ulMaxSendWindow;
// The number of packets acknowledged since the last timeout. The value
// is reset when a timeout occurs or the send window is adjusted upward.
// See 'ulSendWindow'. Access is protected by 'lockT'.
//
ULONG ulAcksSinceSendTimeout;
// The estimated round trip time in milliseconds. This is the RTT value
// from Appendix A of the draft/RFC. The value is adjusted as each
// acknowledge is received. It is initialized to the Packet Processing
// Delay reported by peer. See 'ulSendTimeoutMs'. Access is protected by
// 'lockT'.
//
ULONG ulRoundTripMs;
// The estimated mean deviation in milliseconds, an approximation of the
// standard deviation. This is the DEV value from Appendix A of the
// draft/RFC. The value is adjusted as each acknowledge is received. It
// is initially 0. See 'ulSendTimeoutMs'. Access is protected by
// 'lockT'.
//
LONG lDeviationMs;
// Milliseconds before it is assumed a sent packet will not be
// acknowledged and needs to be retransmitted. This is the ATO value from
// Appendix A of the draft/RFC. This value is adjusted as each
// acknowledge is received, with a maximum of
// 'ADAPTERCB.ulMaxSendTimeoutMs'. Access is protected by 'lockT'.
//
ULONG ulSendTimeoutMs;
// The timer event descriptor scheduled to occur when it is time to stop
// waiting for an outgoing send on which to piggyback an acknowledge.
// This will be NULL when no delayed acknowledge is pending. Per the
// draft/RFC, the timeout used is 1/4 of the 'ulSendTimeoutMs'. Access is
// protected by 'lockT'.
//
TIMERQITEM* pTqiDelayedAck;
// The timer event descriptor which expires when it's time to check for
// lack of any incoming packets. To reduce the cost of constantly
// resetting a Hello timer with a full timeout (which with unsequenced
// payloads usually results in an NdisCancelTimer/NdisSetTimer on each
// received packet), the timeout is broken into intervals of
// L2TP_HelloIntervalMs. If it expires and both 'ulRemainingHelloMs' and
// 'ulHelloResetsThisInterval' are 0, a "Hello" message is sent to the
// peer to verify that the media is still up. Access to this field is
// protected by 'lockT'.
//
TIMERQITEM* pTqiHello;
// The milliseconds left to wait in all remaining Hello intervals and the
// number of resets since the last Hello interval timeout.
//
ULONG ulRemainingHelloMs; ULONG ulHelloResetsThisInterval; // RECEIVE STATE ---------------------------------------------------------
// Next Received, the sequence number one higher than that of the last
// control packet received on this tunnel or 0 if none. Access is
// protected by 'lockT'.
//
USHORT usNr;
// Double-linked list of out-of-order receives, i.e. CONTROLRECEIVEs
// sorted by the 'usNs' field with lower values near the head. The
// maximum queue length is 'ADAPTERCB.sMaxOutOfOrder'. Access is
// protected by 'lockT'.
//
LIST_ENTRY listOutOfOrder;
// TIMER QUEUE -----------------------------------------------------------
// Timer queue for both the control and data channels. The timer queue is
// accessed via the interface defined in timer.h, which handles all
// locking internally.
//
TIMERQ* pTimerQ;
// WORK QUEUE ------------------------------------------------------------
// Double-linked list NDIS_WORK_ITEMs queued for serialized execution at
// PASSIVE IRQL. The next item to be executed is at the head of the list.
// Access is protected via the ScheduleTunnelWork routine, which protects
// the list with 'lockWork'. See also TCBF_InWork.
//
LIST_ENTRY listWork; NDIS_SPIN_LOCK lockWork;
// VC CHAIN --------------------------------------------------------------
// Head of a double-linked list of VCCBs associated with the tunnel, i.e.
// with calls active or in the process of becoming active. New VCs must
// not be linked on closing tunnels, i.e. those with the TCBF_Closing flag
// set. Access to the links is protected by 'lockVcs'.
//
LIST_ENTRY listVcs; NDIS_SPIN_LOCK lockVcs;
// media speed
ULONG ulMediaSpeed; } TUNNELCB;
// Call statistics block.
//
typedef struct _CALLSTATS { // System time call reached established state. When the block is being
// used for cumulative statistics of multiple calls, this is the number of
// calls instead.
//
LONGLONG llCallUp;
// Duration in seconds of now idle call.
//
ULONG ulSeconds;
// Total data bytes received and sent.
//
ULONG ulDataBytesRecd; ULONG ulDataBytesSent;
// Number of received packets indicated up.
//
ULONG ulRecdDataPackets;
// Number of received packets linked on the out-of-order queue before
// being indicated up.
//
ULONG ulDataPacketsDequeued;
// Number of received packets of zero length. Includes packets with the
// R-bit set.
//
ULONG ulRecdZlbs;
// Number of received packets with R-bit set.
//
ULONG ulRecdResets;
// Number of received packets with R-bit set that are out of date.
//
ULONG ulRecdResetsIgnored;
// Number of data packets sent with and without sequence numbers. The sum
// of the two is the total data packets sent.
//
ULONG ulSentDataPacketsSeq; ULONG ulSentDataPacketsUnSeq;
// Number of packets sent that were acknowledged and timed out. If the
// call is cancelled with packets outstanding the sum of the two may be
// less than 'ulSentDataPacketsSeq'.
//
ULONG ulSentPacketsAcked; ULONG ulSentPacketsTimedOut;
// Number of zero length acknowledges sent.
//
ULONG ulSentZAcks;
// Number of packets sent with the R-bit set.
//
ULONG ulSentResets;
// Number of times the send window was changed.
//
ULONG ulSendWindowChanges;
// Total of all send window sizes, one for each 'ulSentDataPacketsSeq'.
//
ULONG ulSendWindowTotal;
// Largest send window.
//
ULONG ulMaxSendWindow;
// Smallest send window.
//
ULONG ulMinSendWindow;
// Number of sample round trips. (sequenced packets only)
//
ULONG ulRoundTrips;
// Total of all round trips in milliseconds. (sequenced packets only)
//
ULONG ulRoundTripMsTotal;
// Longest round trip, (sequenced packets only)
//
ULONG ulMaxRoundTripMs;
// Shortest round trip. (sequenced packets only)
//
ULONG ulMinRoundTripMs; } CALLSTATS;
// Virtual circuit control block defining the state of a single L2TP VC, i.e.
// one line device endpoint and the call, if any, active on it. A VC is never
// used for incoming and outgoing calls simultaneously. A single NDIS VC maps
// to one of these.
//
typedef struct _VCCB { // Links to the prev/next VCCB in the owning tunnel's active VC list.
// Access is protected by 'TUNNELCB.lockVcs'.
//
LIST_ENTRY linkVcs;
// Set to MTAG_VCCB for easy identification in memory dumps and use in
// assertions.
//
ULONG ulTag;
// Reference count on this VC control block. The reference pairs are:
//
// (a) LmpCoCreateVc adds a reference that is removed by LmpCoDeleteVc.
// This covers all clients that learn of the VCCB via NDIS.
//
// (b) LookUpTunnelAndVcCbs adds a reference that is removed at the end of
// the L2tpReceive handler. This covers the receive path.
//
// (c) A reference is added when a CONTROLSENT context with 'pVc'
// referring to this VCCB is assigned the back pointer and removed
// when the context is freed.
//
// (d) A reference is added when a PAYLOADSENT context with 'pVc'
// referring to this VCCB is assigned the back pointer and removed
// when the context is freed.
//
// (e) ScheduleTunnelWork adds a reference that is removed by TunnelWork
// after executing the work.
//
// (f) A reference is added before scheduling the delayed payload
// acknowledge timer and removed in the timer event handler.
//
// (g) A reference is taken by CompleteVcs covering use of the VC popped
// from the tunnel's completing list, and released after use.
//
// (h) A reference is taken prior to calling NdisMCmDispatchIncomingCall
// and removed by the completion handler.
//
// (i) A reference is added when a CONTROLRECEIVED context with 'pVc'
// referring to this VCCB is assigned the back pointer and removed
// when the context is freed.
//
// The field is accessed only by the ReferenceVc and DereferenceVc
// routines, which protect with Interlocked routines.
//
LONG lRef;
// Back pointer to owning adapter's control block.
//
ADAPTERCB* pAdapter;
// Back pointer to owning tunnel's control block or NULL if none.
// Guaranteed valid whenever the VC is linked into a tunnel's 'listVcs',
// i.e. when it holds a reference on the tunnel. It is safe to use this
// if you hold a reference on the call. Otherwise, it is not. Be very
// careful here.
//
TUNNELCB* pTunnel;
// This lock protects VCCB payload send and receive paths as noted in
// other field descriptions. In cases where both 'lockV' and
// 'pTunnel->lockT' are required 'lockT' must be obtained first.
//
NDIS_SPIN_LOCK lockV;
// CALL SETUP ------------------------------------------------------------
// Our unique call identifier sent back to us by peer in the L2TP header.
// The value is a 1-based index into the 'ADAPTERCB.ppVcs' array.
//
USHORT usCallId;
// The call identifier, chosen by peer, that we send back to him in the
// L2TP header Call-ID field for all packets on this call. A value of 0
// indicates no Call-ID has been assigned.
//
USHORT usAssignedCallId;
// VCBF_* bit flags indicating various options and states. Access is via
// the interlocked ReadFlags/SetFlags/ClearFlags routines.
//
// VCBF_IndicateReceivedTime: Set if MakeCall caller sets the
// MediaParameters.Flags RECEIVE_TIME_INDICATION flag requesting the
// TimeReceived field of the NDIS packet be filled with a timestamp.
//
// VCBF_CallClosableByClient: Set when a call is in a state where
// LcmCmCloseCall requests to initiate clean-up should be accepted.
// This may be set when VCBF_CallClosableByPeer is not, which means we
// have indicated an incoming close to client and are waiting for him
// to do a client close in response (in that weird CoNDIS way). The
// flag is protected by 'lockV'.
//
// VCBF_CallClosableByPeer: Set when the call is in a state where an idle
// transition without operations pending should be mapped to a
// PeerClose event. This will never be set when
// VCBF_CallClosableByClient is not. The flag is protected by
// 'lockV'.
//
// VCBF_DefaultLcParams: Set when the 'pLcParams' field was allocated by
// us rather than being owned by client.
//
// VCBF_IncomingFsm: Set when the VC is executing the Incoming Call FSM
// rather than Outgoing Call FSM in the active incoming/outgoing call.
// For client initiated calls this will set if the adapter's
// ACBF_OutgoingRoleLac flag, read from the registry, is set.
//
// VCBF_PeerInitiatedCall: Set when an the active call was initiated by
// the peer, clear if it was initiated by the client.
//
// VCBF_Sequencing: Set unless no Receive Window AVP is provided/received
// during call setup, resulting in "no sequencing" mode where Ns/Nr
// fields are not sent in the payload header. This also effectively
// disables out-of-order processing.
//
// VCBF_VcCreated: Set when the VC has been created successfully. This is
// the "creation" that occurs with the client, not the mini-port.
// VCBF_VcActivated: Set when the VC has been activated successfully.
// VCBF_VcDispatched: Set when the VC has dispatched an incoming call to
// the client and client has returned success or pended.
// VCBM_VcState: Bit mask including each of the above 3 NDIS state flags.
//
// VCBF_VcDeleted: Set when the DeleteVC handler has been called on this
// VC. This guards against NDPROXY double-deleting VCs which it has
// been known to do.
//
// The pending bits below are mutually exclusive (except ClientClose which
// may occur after but simultaneous with ClientOpen), and so require lock
// protection by 'lockV':
//
// VCBF_PeerOpenPending: Set when peer attempts to establish a call, and
// the result is not yet known.
// VCBF_ClientOpenPending: Set when client attempts to establish a call,
// and the result is not yet known.
// VCBF_PeerClosePending: Set when peer attempts to close an established
// call and the result is not yet known. Access is protected by
// 'lockV'.
// VCBF_ClientClosePending: Set when client attempts to close an
// established call and the result is not yet known. Access is
// protected by 'lockV'.
// VCBM_Pending: Bit mask that includes each of the 4 pending flags.
//
// VCBF_ClientCloseCompletion: Set when client close completion is in
// progress.
//
// VCBF_IcsAlloc: Set when the 'pInCall' block has been locked for
// allocation and cleared when the call is torn down. Accessed only
// by the LockIcs/UnlockIcs routines.
// VCBF_IcsGrace: Set when the 'pInCall' pointer has been locked for a
// grace period during which the response to the incoming call message
// is sent. Accessed only by the LockIcs/UnlockIcs routines.
//
// VCBF_WaitInCallComplete: Set when the client is expected to call our
// call manager's IncomingCallComplete handler. This guards against
// NDPROXY double completing calls which it has been known to do.
// VCBF_WaitCloseCall: Set when the client is expected to call our call
// manager's CloseCall handler. This is strictly a debug aid.
//
// VCBF_CompPending: Set when this VC is put on tunnel's listCompletingVcs list
//
ULONG ulFlags; #define VCBF_IndicateTimeReceived 0x00000001
#define VCBF_CallClosableByClient 0x00000002
#define VCBF_CallClosableByPeer 0x00000004
#define VCBF_DefaultLcParams 0x00000008
#define VCBF_IncomingFsm 0x00000010
#define VCBF_PeerInitiatedCall 0x00000020
#define VCBF_Sequencing 0x00000040
#define VCBF_VcCreated 0x00000100
#define VCBF_VcActivated 0x00000200
#define VCBF_VcDispatched 0x00000400
#define VCBM_VcState 0x00000700
#define VCBF_PeerOpenPending 0x00001000
#define VCBF_ClientOpenPending 0x00002000
#define VCBF_PeerClosePending 0x00004000
#define VCBF_ClientClosePending 0x00008000
#define VCBM_Pending 0x0000F000
#define VCBF_VcDeleted 0x00010000
#define VCBF_ClientCloseCompletion 0x00020000
#define VCBF_IcsAlloc 0x00040000
#define VCBF_IcsGrace 0x00080000
#define VCBF_WaitInCallComplete 0x00100000
#define VCBF_WaitCloseCall 0x00200000
#define VCBF_CompPending 0x01000000
// Reference count on the active call. Fields in this CALL SETUP section
// and in the CALL STATISTICS section should not be accessed without a
// call reference while the VC is activated. References may only be added
// when the VCCB_VcActivated flag is set, and this is enforced by
// ReferenceCall. The reference pairs are:
//
// (a) A reference is added when a VC is activated and removed when it is
// de-activated.
//
// (b) A reference is added when the send handler accepts a packet. For
// unsequenced sends the reference is removed by the send complete
// routine. For sequenced sends it it removed when the PAYLOADSENT
// context is destroyed.
//
// (c) A reference is added before scheduling a ZLB send and removed by
// the send completion routine.
//
// (d) A reference is added before entering ReceivePayload and removed on
// exit from same.
//
// (e) A reference is added before dispatching the call that is removed
// when the dispatch is completed.
//
// The field is accessed only by the ReferenceCall and DereferenceCall
// routines, which protect the field with 'lockCall'.
//
LONG lCallRef; NDIS_SPIN_LOCK lockCall;
// The current state of the VCs call creation, i.e. the control channel's
// data channel setup for this VC. Access is protected by 'lockV' once
// the VC is set up to receive call control messages.
//
L2TPCALLSTATE state;
// Links to the prev/next VCCB in the owning tunnel's requesting VC list
// VC list. Access is protected by 'TUNNELCB.lockT'.
//
LIST_ENTRY linkRequestingVcs;
// Links to the prev/next VCCB in the owning tunnel's completing VC list.
// Access is protected by 'TUNNELCB.lockT'.
//
LIST_ENTRY linkCompletingVcs;
// This is set to the pending peer open/close or client open operation
// result to be reported to client.
//
NDIS_STATUS status;
// The received call setup message context. When peer initiates a call,
// we must create a VC and dispatch the incoming call to the client above.
// This is an asynchronous operation that must occur right in the middle
// of receive processing. This context stores information about the
// received message so it can be processed when it is known if client will
// accept the call. It also includes the CO_CALL_PARAMETERS buffer
// dispatched to client on incoming calls. The field is valid only until
// LcmCmIncomingCallComplete handler is called, at which time it is set to
// NULL.
//
// Shortcut addresses of the TAPI call info passed up in the
// NdisMCmDispatchIncomingCall. Obviously, they are valid only when
// 'pInCall' is valid. When invalid they are set to NULL.
//
INCALLSETUP* pInCall; CO_AF_TAPI_INCOMING_CALL_PARAMETERS UNALIGNED * pTiParams; LINE_CALL_INFO* pTcInfo;
// Reference count on the 'pInCall' context. The reference pairs are:
//
// (a) A reference is added when the context is allocated and removed
// by CallSetupComplete.
//
// (b) A reference is added before passing addresses within the context to
// ReceiveControlExpected and removed after that routine returns.
//
// The field is accessed only by the ReferenceIcs and DereferenceIcs
// routines, which protect with Interlocked routines. An exception is
// initializion to 1 by SetupVcAsynchronously.
//
LONG lInCallRef;
// Address of the call parameters passed down in CmMakeCall. This field
// will only be valid until the NdisMCmMakeCallComplete notification for
// the associated call is made, at which time it is reset to NULL. Access
// is via Interlocked routines.
//
// Shortcut addresses of the TAPI call parameters (both levels) and the
// L2TP-specific call parameters in the 'pMakeCall' buffer. Obviously,
// they are valid only when 'pMakeCall' is valid. When invalid they are
// set to NULL.
//
CO_CALL_PARAMETERS* pMakeCall; CO_AF_TAPI_MAKE_CALL_PARAMETERS UNALIGNED* pTmParams; LINE_CALL_PARAMS* pTcParams;
// Shortcut address of the L2TP-specific call parameters in the
// 'pMakeCall' or 'pInCall' buffer. Obviously, this is only valid when
// 'pMakeCall' or 'pInCall' is non-NULL. When invalid this is NULL. On
// MakeCall, caller may not provide 'pLcParams' in which case one is
// allocated and initialized to defaults for the convenience of the rest
// of the code. This temporary buffer is not reported to caller on
// MakeCallComplete.
//
L2TP_CALL_PARAMETERS* pLcParams;
// The result and error to report in the coming incoming/outgoing call
// reply message.
//
USHORT usResult; USHORT usError;
// The connect speed in bits/second. This is the transmit speed value
// reported by the peer LAC, or the value we reported to the peer LNS and
// to NDISWAN. Since we have no real knowledge of connect speed, we
// report the minimum of the maximum rate acceptable to peer and
// L2TP_LanBps.
//
ULONG ulConnectBps;
// SEND STATE ------------------------------------------------------------
// Next Sent, the sequence number of next payload packet transmitted on
// this call. The field is initialized to 0 and incremented after
// assignment to an outgoing packet, excepting retransmissions. Access is
// protected by 'lockV'.
//
USHORT usNs;
// Double-linked list of outstanding sends, i.e. PAYLOADSENTs sorted by
// the 'usNs' field with lower values near the head. Access is protected
// by 'lockV'.
//
LIST_ENTRY listSendsOut;
// The number of sent but unacknowledged packets that may be outstanding.
// This value is adjusted dynamically. Per the draft/RFC, when
// 'ulAcksSinceSendTimeout' reaches the current setting, the window is
// increased by one. When a send timeout expires the window is reduced by
// half. The actual send window throttling is done by NDISWAN, based on
// our indications of the changing window size. Access is protected by
// 'lockV'.
//
ULONG ulSendWindow;
// The maximum value of 'ulSendWindow'. Peer chooses this value during
// call setup.
//
ULONG ulMaxSendWindow;
// The number of packets acknowledged since the last timeout. The value
// is reset when a timeout occurs or the send window is adjusted upward.
// See 'ulSendWindow'. Access is protected by 'lockV'.
//
ULONG ulAcksSinceSendTimeout;
// The estimated round trip time in milliseconds. This is the RTT value
// from Appendix A of the draft/RFC. The value is adjusted as each
// acknowledge is received. It is initialized to the Packet Processing
// Delay reported by peer. See 'ulSendTimeoutMs'. Access is protected by
// 'lockV'.
//
ULONG ulRoundTripMs;
// The estimated mean deviation in milliseconds, an approximation of the
// standard deviation. This is the DEV value from Appendix A of the
// draft/RFC. The value is adjusted as each acknowledge is received. It
// is initially 0. See 'ulSendTimeoutMs'. Access is protected by
// 'lockV'.
//
LONG lDeviationMs;
// Milliseconds before it is assumed a sent packet will never be
// acknowledged. This is the ATO value from Appendix A of the draft/RFC.
// This value is adjusted as each acknowledge is received, with a maximum
// of 'ADAPTERCB.ulMaxSendTimeoutMs'. Access is protected by 'lockV'.
//
ULONG ulSendTimeoutMs;
// The timer event descriptor scheduled to occur when it is time to stop
// waiting for an outgoing send on which to piggyback an acknowledge.
// This will be NULL when no delayed acknowledge is pending. Per the
// draft/RFC, the timeout used is 1/4 of the 'ulSendTimeoutMs'. Access is
// protected by 'lockV'.
//
TIMERQITEM* pTqiDelayedAck;
// RECEIVE STATE ---------------------------------------------------------
// Next Received, the sequence number one higher than that of the last
// payload packet received on this call or 0 if none. Access is protected
// by 'lockV'.
//
USHORT usNr;
// Double-linked list of out-of-order receives, i.e. PAYLOADRECEIVEs
// sorted by the 'usNs' field with lower values near the head. The
// maximum queue length is 'ADAPTERCB.sMaxOutOfOrder'. Access is
// protected by 'lockV'.
//
LIST_ENTRY listOutOfOrder;
// NDIS BOOKKEEPING ------------------------------------------------------
// NDIS's handle for this VC passed to us in MiniportCoCreateVcHandler.
// This is passed back to NDIS in various NdisXxx calls.
//
NDIS_HANDLE NdisVcHandle;
// Configuration settings returned to callers on OID_WAN_CO_GET_INFO and
// modified by callers on OID_WAN_CO_SET_INFO. Older NDISWAN references to
// "LINK" map straight to "VC" in the NDIS 5.0 world. Access is not
// protected because each ULONG in the structure is independent so no
// incoherency can result from multiple access.
//
NDIS_WAN_CO_GET_LINK_INFO linkinfo;
// STATISTICS ------------------------------------------------------------
// Statistics for the current call. Access is protected by 'lockV'.
//
CALLSTATS stats; } VCCB;
// The "exploded" description of an L2TP header, as output by
// ExplodeL2tpHeader.
//
typedef struct _L2TPHEADERINFO { // Addresses of header fields. Some may be NULL indicating the field was
// not present in the header.
//
USHORT* pusBits; USHORT* pusLength; USHORT* pusTunnelId; USHORT* pusCallId; USHORT* pusNs; USHORT* pusNr;
// Length of the variable length header in bytes.
//
ULONG ulHeaderLength;
// Address and length in bytes of the data following the variable length
// header.
//
CHAR* pData; ULONG ulDataLength; } L2TPHEADERINFO;
// The "exploded" description of an Attribute/Value Pair (AVP), as output by
// ExplodeAvpHeader. The "value" is located and sized but not interpreted or
// byte-ordered until a GetAvpValueXxx routine is applied.
//
typedef struct _AVPINFO { // Addresses of header fields. All are always present.
//
UNALIGNED USHORT* pusBits; UNALIGNED USHORT* pusVendorId; UNALIGNED USHORT* pusAttribute;
// The length of the entire AVP, extracted from '*pusBits'.
//
USHORT usOverallLength;
// Length of the value in bytes and the address of the value.
//
USHORT usValueLength; CHAR* pValue; } AVPINFO;
// The "exploded" description of a control message, as output by
// ExplodeControlAvps.
//
typedef struct _CONTROLMSGINFO { // GERR_* code indicating the result of the ExplodeControlAvps operation.
// Other fields should not be referenced unless this is GERR_None.
//
USHORT usXError;
// True when the message is a tunnel setup message, false if it is a call
// setup message.
//
BOOLEAN fTunnelMsg;
// Address of message type AVP value. The message type AVP is present in
// all valid control messages.
//
UNALIGNED USHORT* pusMsgType;
// Addresses of additional AVP values. These may be NULL indicating the
// AVP was not found in the message. The length field following variable
// length fields is valid whenever the value address is non-NULL.
//
USHORT* pusResult; USHORT* pusError; CHAR* pchResultMsg; USHORT usResultMsgLength; UNALIGNED USHORT* pusProtocolVersion; UNALIGNED USHORT* pusFirmwareRevision; UNALIGNED ULONG* pulFramingCaps; UNALIGNED ULONG* pulBearerCaps; CHAR* pchTieBreaker; CHAR* pchHostName; USHORT usHostNameLength; UNALIGNED USHORT* pusAssignedTunnelId; UNALIGNED USHORT* pusRWindowSize; UNALIGNED USHORT* pusAssignedCallId; UNALIGNED ULONG* pulCallSerialNumber; UNALIGNED ULONG* pulMinimumBps; UNALIGNED ULONG* pulMaximumBps; UNALIGNED ULONG* pulBearerType; UNALIGNED ULONG* pulFramingType; UNALIGNED USHORT* pusPacketProcDelay; CHAR* pchDialedNumber; USHORT usDialedNumberLength; CHAR* pchDialingNumber; USHORT usDialingNumberLength; UNALIGNED ULONG* pulTxConnectSpeed; UNALIGNED ULONG* pulPhysicalChannelId; CHAR* pchSubAddress; USHORT usSubAddressLength; CHAR* pchChallenge; USHORT usChallengeLength; CHAR* pchResponse; UNALIGNED USHORT* pusProxyAuthType; CHAR* pchProxyAuthResponse; USHORT usProxyAuthResponseLength; UNALIGNED ULONG* pulCallErrors; UNALIGNED ULONG* pulAccm; BOOLEAN fSequencingRequired; } CONTROLMSGINFO;
// Context for a control packet received out of order which is queued rather
// than discarding in the hope that the missing packet will arrive.
//
typedef struct _CONTROLRECEIVED { // Link to the prev/next link in the 'TUNNELCB.listOutOfOrder' list.
//
LIST_ENTRY linkOutOfOrder;
// 'Next Sent' sequence number received in the packet.
//
USHORT usNs;
// Associated VC or NULL if none.
//
VCCB* pVc;
// The received GetBufferFromPool buffer.
//
CHAR* pBuffer;
// The "exploded" description of the control message.
//
CONTROLMSGINFO control; } CONTROLRECEIVED;
// Context for a control packet sent but not yet acknowledged. This block is
// queued on the 'TUNNELCB.listSendsOut' and 'TUNNELCB.listSendsPending'
// lists, and is associated with SendControlTimerEvents.
//
typedef struct _CONTROLSENT { // Link to the prev/next link in the 'TUNNELCB.listSendsOut' list.
//
LIST_ENTRY linkSendsOut;
// Reference count on this context. The reference pairs are:
//
// (a) A reference is added when the context is queued into the
// 'listSendsOut' list, and removed by the de-queuer.
//
// (b) A reference is added before sending (and also before
// 'pTqiSendTimeout' is scheduled) and is removed by the send
// completion routine.
//
// (c) A reference is added before 'pTqiSendTimeout' is scheduled and
// removed as the timer event handler exits.
//
LONG lRef;
// 'Next Sent' sequence number sent with the packet.
//
USHORT usNs;
// The message type of the packet. (debug use only)
//
USHORT usMsgType;
// Timer event descriptor scheduled for the packet.
//
TIMERQITEM* pTqiSendTimeout;
// Number of times the packet has been retransmitted.
//
ULONG ulRetransmits;
// CSF_* flags indicating various options.
//
// CSF_Pending: Set when transmission or retransmission of the packet is
// pending. Access is protected by 'pTunnel->lockT'.
//
// CSF_TunnelIdleOnAck: Set when TunnelTransitionComplete is to be
// executed when the message is acknowledged, moving to CCS_Idle
// state.
//
// CSF_CallIdleOnAck: Set when CallTransitionComplete is to be executed
// when the message is acknowledged, moving to CS_Idle state.
//
ULONG ulFlags; #define CSF_Pending 0x00000001
#define CSF_TunnelIdleOnAck 0x00000010
#define CSF_CallIdleOnAck 0x00000020
#define CSF_QueryMediaSpeed 0x00000040
#define CSF_IpUdpHeaders 0x00000080
// The outstanding packet's buffer, as passed to TDI.
//
CHAR* pBuffer;
// The length of the data to send in 'pBuffer'.
//
ULONG ulBufferLength;
// Back pointer to owning tunnel.
//
TUNNELCB* pTunnel;
// Back pointer to owning VC, or NULL if none.
//
VCCB* pVc;
// The NDIS system time at which the packet was originally sent.
//
LONGLONG llTimeSent;
// The IRP passed to TDI by the TDIX extension library, or NULL if none or
// it's already been completed. (for debug purposes only)
//
IRP* pIrp; } CONTROLSENT;
// Context for a payload packet received out of order which is queued for a
// time rather than discarding in the hope that the missing packet will
// arrive.
//
typedef struct _PAYLOADRECEIVED { // Link to the prev/next link in the 'VCCB.listOutOfOrder' list.
//
LIST_ENTRY linkOutOfOrder;
// 'Next Sent' sequence number received in the packet.
//
USHORT usNs;
// The received GetBufferFromPool buffer.
//
CHAR* pBuffer;
// Offset of the payload to indicate received in 'pBuffer'.
//
ULONG ulPayloadOffset;
// Length in bytes of the payload to indicate received in 'pBuffer'.
//
ULONG ulPayloadLength;
// NDIS time the packet was received from the net, or 0 if caller did not
// choose the RECEIVE_TIME_INDICATION option in his call parameters.
//
LONGLONG llTimeReceived; } PAYLOADRECEIVED;
// Context for a payload packet sent but not yet acknowledged. This block is
// queued on the 'VCCB.listSendsOut', and is associated with
// SendPayloadTimerEvents.
//
typedef struct _PAYLOADSENT { // Link to the prev/next link in the 'VCCB.listSendsOut' list.
//
LIST_ENTRY linkSendsOut;
// Link to the prev/next link in the 'g_listDebugPs' list. The list is
// maintained only when PSDEBUG is defined, but this is included always
// for the convenience of KD extension users. (for debug purposes only)
//
LIST_ENTRY linkDebugPs;
// Reference count on this context. The reference pairs are:
//
// (a) A reference is added when the context is queued into the
// 'listSendsOut' list, and removed by the de-queuer.
//
// (b) A reference is added before sending (and also before the time is
// scheduled) and removed by the send completion routine.
//
// (c) A reference is added before scheduling the timer and removed by the
// timer event handler.
//
LONG lRef;
// 'Next Sent' sequence number sent with the packet.
//
USHORT usNs;
// Timer event descriptor scheduled to fire when it's time to give up on
// receiving an acknowledge of the packet.
//
TIMERQITEM* pTqiSendTimeout;
// The built NDIS packet.
//
NDIS_PACKET* pPacket;
// The L2TP header buffer prepended to the payload buffer.
//
CHAR* pBuffer;
// Back pointer to the owning tunnel control block.
//
TUNNELCB* pTunnel;
// Back pointer to the owning VC control block.
//
VCCB* pVc;
// Status of the completed packet.
//
NDIS_STATUS status;
// The NDIS system time at which the packet was originally sent.
//
LONGLONG llTimeSent;
// The IRP passed to TDI by the TDIX extension library, or NULL if none or
// it's already been completed. (for debug purposes only)
//
IRP* pIrp; } PAYLOADSENT;
// Tunnel work handler that executes tunnel related work at PASSIVE IRQL.
// 'PWork' is the work context that should be freed with FREE_TUNNELWORK when
// the handler is done accessing the 'punpArgs' array. 'PTunnel' is the
// owning tunnel. 'PVc' is the owning VC, or NULL if none. 'PunpArgs' is an
// array of 4 auxillary arguments as passed to ScheduleTunnelWork.
//
typedef VOID (*PTUNNELWORK)( IN TUNNELWORK* pWork, IN TUNNELCB* pTunnel, IN VCCB* pVc, IN ULONG_PTR* punpArgs );
// Tunnel work item describing a single unit of tunnel related work to be
// executed serially at PASSIVE IRQL by the TunnelWork mechanism.
//
typedef struct _TUNNELWORK { // Link to the prev/next link in the 'TUNNELCB.listWork' queue.
//
LIST_ENTRY linkWork;
// Handler that executes this work item.
//
PTUNNELWORK pHandler;
// The associated VC, if any.
//
VCCB* pVc;
// Auxillary arguments passed to handler.
//
ULONG_PTR aunpArgs[ 4 ]; } TUNNELWORK;
// Context of call setup for an incoming call. The information is used to
// store and later resume receive processing of an peer's call initiation
// across the asynchronous CoNdis calls, and for building the call parameter
// buffer to dispatch to client.
//
typedef struct _INCALLSETUP { // See ReceiveControl for descriptions.
//
CHAR* pBuffer; L2TPHEADERINFO info; CONTROLMSGINFO control;
// Buffer in which the incoming call parameters to be dispatched to caller
// are built.
//
PVOID pvDummyPointerAligner; CHAR achCallParams[ sizeof(CO_CALL_PARAMETERS)
+ sizeof(PVOID) + sizeof(CO_CALL_MANAGER_PARAMETERS)
+ sizeof(PVOID) + sizeof(CO_MEDIA_PARAMETERS) + sizeof(CO_AF_TAPI_INCOMING_CALL_PARAMETERS)
+ sizeof(PVOID) + sizeof(LINE_CALL_INFO)
+ sizeof(PVOID) + sizeof(L2TP_CALL_PARAMETERS)
+ ((L2TP_MaxDottedIpLen + 1) * sizeof(WCHAR)) ]; } INCALLSETUP;
// The L2TP role played by an L2TP peer. The values may be read from the
// registry, so don't change randomly.
//
typedef enum _L2TPROLE { LR_Lns = 1, LR_Lac = 2 } L2TPROLE;
// The strategy employed when it is time to add a host route and that route is
// found to already exists.
//
// Note: The values currently match the those of the registry parameter
// "UseExistingRoutes". Check GetRegistrySettings code before changing.
//
typedef enum _HOSTROUTEEXISTS { HRE_Use = 0, HRE_Fail = 1, HRE_Reference = 2 } HOSTROUTEEXISTS;
// Link status block for transfer across locks. See TransferLinkStatusInfo
// and IndicateLinkStatus.
//
typedef struct _LINKSTATUSINFO { NDIS_HANDLE MiniportAdapterHandle; NDIS_HANDLE NdisVcHandle; WAN_CO_LINKPARAMS params; } LINKSTATUSINFO;
//-----------------------------------------------------------------------------
// Macros/inlines
//-----------------------------------------------------------------------------
#define CtrlObjFromUdpContext(_x) \
(_x)->pCtrlAddr #define PayloadObjFromUdpContext(_x) \
(_x)->pPayloadAddr // These basics are not in the DDK headers for some reason.
//
#define min( a, b ) (((a) < (b)) ? (a) : (b))
#define max( a, b ) (((a) > (b)) ? (a) : (b))
#define InsertBefore( pNewL, pL ) \
{ \ (pNewL)->Flink = (pL); \ (pNewL)->Blink = (pL)->Blink; \ (pNewL)->Flink->Blink = (pNewL); \ (pNewL)->Blink->Flink = (pNewL); \ }
#define InsertAfter( pNewL, pL ) \
{ \ (pNewL)->Flink = (pL)->Flink; \ (pNewL)->Blink = (pL); \ (pNewL)->Flink->Blink = (pNewL); \ (pNewL)->Blink->Flink = (pNewL); \ }
// Pad to the size of the given datatype. (Borrowed from wdm.h which is not
// otherwise needed)
//
#define ALIGN_DOWN(length, type) \
((ULONG)(length) & ~(sizeof(type) - 1))
#define ALIGN_UP(length, type) \
(ALIGN_DOWN(((ULONG)(length) + sizeof(type) - 1), type))
// Winsock-ish host/network byte order converters for short and long integers.
//
#if (defined(_M_IX86) && (_MSC_FULL_VER > 13009037)) || ((defined(_M_AMD64) || defined(_M_IA64)) && (_MSC_FULL_VER > 13009175))
#define htons(x) _byteswap_ushort((USHORT)(x))
#define htonl(x) _byteswap_ulong((ULONG)(x))
#else
#define htons( a ) ((((a) & 0xFF00) >> 8) |\
(((a) & 0x00FF) << 8)) #define htonl( a ) ((((a) & 0xFF000000) >> 24) | \
(((a) & 0x00FF0000) >> 8) | \ (((a) & 0x0000FF00) << 8) | \ (((a) & 0x000000FF) << 24)) #endif
#define ntohs( a ) htons(a)
#define ntohl( a ) htonl(a)
// network byte order
#define IPADDR_IS_MULTICAST(_addr) (((_addr) & 0x000000f0) == 0x000000e0)
#define IPADDR_IS_BROADCAST(_addr) ((_addr) == 0xffffffff)
// Place in a TRACE argument list to correspond with a format of "%d.%d.%d.%d"
// to print network byte-ordered IP address 'x' in human readable form.
//
#define IPADDRTRACE( x ) ((x) & 0x000000FF), \
(((x) >> 8) & 0x000000FF), \ (((x) >> 16) & 0x000000FF), \ (((x) >> 24) & 0x000000FF)
// Place in a TRACE argument list to correspond with a format of "%d" to print
// a percentage of two integers, or an average of two integers, or those
// values rounded.
//
#define PCTTRACE( n, d ) ((d) ? (((n) * 100) / (d)) : 0)
#define AVGTRACE( t, c ) ((c) ? ((t) / (c)) : 0)
#define PCTRNDTRACE( n, d ) ((d) ? (((((n) * 1000) / (d)) + 5) / 10) : 0)
#define AVGRNDTRACE( t, c ) ((c) ? (((((t) * 10) / (c)) + 5) / 10) : 0)
// All memory allocations and frees are done with these ALLOC_*/FREE_*
// macros/inlines to allow memory management scheme changes without global
// editing. For example, might choose to lump several lookaside lists of
// nearly equal sized items into a single list for efficiency.
//
// NdisFreeMemory requires the length of the allocation as an argument. NT
// currently doesn't use this for non-paged memory, but according to JameelH,
// Windows95 does. These inlines stash the length at the beginning of the
// allocation, providing the traditional malloc/free interface. The
// stash-area is a ULONGLONG so that all allocated blocks remain ULONGLONG
// aligned as they would be otherwise, preventing problems on Alphas.
//
__inline VOID* ALLOC_NONPAGED( IN ULONG ulBufLength, IN ULONG ulTag ) { CHAR* pBuf;
NdisAllocateMemoryWithTag( &pBuf, (UINT )(ulBufLength + MEMORY_ALLOCATION_ALIGNMENT), ulTag ); if (!pBuf) { return NULL; }
((ULONG* )pBuf)[ 0 ] = ulBufLength; ((ULONG* )pBuf)[ 1 ] = 0xC0BBC0DE; return pBuf + MEMORY_ALLOCATION_ALIGNMENT; }
__inline VOID FREE_NONPAGED( IN VOID* pBuf ) { ULONG ulBufLen;
ulBufLen = *((ULONG* )(((CHAR* )pBuf) - MEMORY_ALLOCATION_ALIGNMENT)); NdisFreeMemory( ((CHAR* )pBuf) - MEMORY_ALLOCATION_ALIGNMENT, (UINT )(ulBufLen + MEMORY_ALLOCATION_ALIGNMENT), 0 ); }
#define ALLOC_NDIS_WORK_ITEM( pA ) \
NdisAllocateFromNPagedLookasideList( &(pA)->llistWorkItems ) #define FREE_NDIS_WORK_ITEM( pA, pNwi ) \
NdisFreeToNPagedLookasideList( &(pA)->llistWorkItems, (pNwi) )
#define ALLOC_TIMERQITEM( pA ) \
NdisAllocateFromNPagedLookasideList( &(pA)->llistTimerQItems ) #define FREE_TIMERQITEM( pA, pTqi ) \
NdisFreeToNPagedLookasideList( &(pA)->llistTimerQItems, (pTqi) )
#define ALLOC_CONTROLSENT( pA ) \
NdisAllocateFromNPagedLookasideList( &(pA)->llistControlSents ) #define FREE_CONTROLSENT( pA, pCs ) \
NdisFreeToNPagedLookasideList( &(pA)->llistControlSents, (pCs) )
#define ALLOC_PAYLOADSENT( pA ) \
NdisAllocateFromNPagedLookasideList( &(pA)->llistPayloadSents ) #define FREE_PAYLOADSENT( pA, pPs ) \
NdisFreeToNPagedLookasideList( &(pA)->llistPayloadSents, (pPs) )
#define ALLOC_TUNNELWORK( pA ) \
NdisAllocateFromNPagedLookasideList( &(pA)->llistTunnelWorks ) #define FREE_TUNNELWORK( pA, pCs ) \
NdisFreeToNPagedLookasideList( &(pA)->llistTunnelWorks, (pCs) )
#if LLISTALL
#define ALLOC_TUNNELCB( pA ) \
NdisAllocateFromNPagedLookasideList( &(pA)->llistTunnels ) #define FREE_TUNNELCB( pA, pT ) \
NdisFreeToNPagedLookasideList( &(pA)->llistTunnels, (pT) )
#define ALLOC_VCCB( pA ) \
NdisAllocateFromNPagedLookasideList( &(pA)->llistVcs ) #define FREE_VCCB( pA, pV ) \
NdisFreeToNPagedLookasideList( &(pA)->llistVcs, (pV) )
#define ALLOC_TIMERQ( pA ) \
NdisAllocateFromNPagedLookasideList( &(pA)->llistTimerQs ) #define FREE_TIMERQ( pA, pTq ) \
NdisFreeToNPagedLookasideList( &(pA)->llistTimerQs, (pTq) )
#define ALLOC_CONTROLRECEIVED( pA ) \
NdisAllocateFromNPagedLookasideList( &(pA)->llistControlReceiveds ) #define FREE_CONTROLRECEIVED( pA, pCr ) \
NdisFreeToNPagedLookasideList( &(pA)->llistControlReceiveds, (pCr) )
#define ALLOC_PAYLOADRECEIVED( pA ) \
NdisAllocateFromNPagedLookasideList( &(pA)->llistPayloadReceiveds ) #define FREE_PAYLOADRECEIVED( pA, pPr ) \
NdisFreeToNPagedLookasideList( &(pA)->llistPayloadReceiveds, (pPr) )
#define ALLOC_INCALLSETUP( pA ) \
NdisAllocateFromNPagedLookasideList( &(pA)->llistInCallSetups ) #define FREE_INCALLSETUP( pA, pCs ) \
NdisFreeToNPagedLookasideList( &(pA)->llistInCallSetups, (pCs) )
#else // !LLISTALL
#define ALLOC_TUNNELCB( pA ) \
ALLOC_NONPAGED( sizeof(TUNNELCB), MTAG_TUNNELCB ) #define FREE_TUNNELCB( pA, pT ) \
FREE_NONPAGED( pT )
#define ALLOC_VCCB( pA ) \
ALLOC_NONPAGED( sizeof(VCCB), MTAG_VCCB ) #define FREE_VCCB( pA, pV ) \
FREE_NONPAGED( pV )
#define ALLOC_TIMERQ( pA ) \
ALLOC_NONPAGED( sizeof(TIMERQ), MTAG_TIMERQ ) #define FREE_TIMERQ( pA, pTq ) \
FREE_NONPAGED( pTq )
#define ALLOC_CONTROLRECEIVED( pA ) \
ALLOC_NONPAGED( sizeof(CONTROLRECEIVED), MTAG_CTRLRECD ) #define FREE_CONTROLRECEIVED( pA, pCr ) \
FREE_NONPAGED( pCr )
#define ALLOC_PAYLOADRECEIVED( pA ) \
ALLOC_NONPAGED( sizeof(PAYLOADRECEIVED), MTAG_PAYLRECD ) #define FREE_PAYLOADRECEIVED( pA, pPr ) \
FREE_NONPAGED( pPr )
#define ALLOC_INCALLSETUP( pA ) \
ALLOC_NONPAGED( sizeof(INCALLSETUP), MTAG_INCALL ) #define FREE_INCALLSETUP( pA, pCs ) \
FREE_NONPAGED( pCs )
#define ALLOC_CONTROLMSGINFO( pA ) \
NdisAllocateFromNPagedLookasideList( &(pA)->llistControlMsgInfos ) #define FREE_CONTROLMSGINFO( pA, pCmi ) \
NdisFreeToNPagedLookasideList( &(pA)->llistControlMsgInfos, (pCmi) )
#endif // !LLISTALL
#if READFLAGSDIRECT
#define ReadFlags( pulFlags ) \
(*pulFlags)
#endif
//-----------------------------------------------------------------------------
// Prototypes (alphabetically)
//-----------------------------------------------------------------------------
VOID ActivateCallIdSlot( IN VCCB* pVc );
VOID AddHostRoute( IN TUNNELWORK* pWork, IN TUNNELCB* pTunnel, IN VCCB* pVc, IN ULONG_PTR* punpArgs );
BOOLEAN AdjustSendWindowAtAckReceived( IN ULONG ulMaxSendWindow, IN OUT ULONG* pulAcksSinceSendTimeout, IN OUT ULONG* pulSendWindow );
VOID AdjustTimeoutsAtAckReceived( IN LONGLONG llSendTime, IN ULONG ulMaxSendTimeoutMs, OUT ULONG* pulSendTimeoutMs, IN OUT ULONG* pulRoundTripMs, IN OUT LONG* plDeviationMs );
VOID AdjustTimeoutsAndSendWindowAtTimeout( IN ULONG ulMaxSendTimeoutMs, IN LONG lDeviationMs, OUT ULONG* pulSendTimeoutMs, IN OUT ULONG* pulRoundTripMs, IN OUT ULONG* pulSendWindow, OUT ULONG* pulAcksSinceSendTimeout );
VOID CalculateResponse( IN UCHAR* puchChallenge, IN ULONG ulChallengeLength, IN CHAR* pszPassword, IN UCHAR uchId, OUT UCHAR* puchResponse );
VOID CallCleanUp( IN VCCB* pVc );
VOID CallTransitionComplete( IN TUNNELCB* pTunnel, IN VCCB* pVc, IN L2TPCALLSTATE state );
VOID ChangeHostRoute( IN TUNNELWORK* pWork, IN TUNNELCB* pTunnel, IN VCCB* pVc, IN ULONG_PTR* punpArgs );
VOID ClearFlags( IN OUT ULONG* pulFlags, IN ULONG ulMask );
VOID CloseCall( IN TUNNELWORK* pWork, IN TUNNELCB* pTunnel, IN VCCB* pVc, IN ULONG_PTR* punpArgs );
BOOLEAN CloseCall2( IN TUNNELCB* pTunnel, IN VCCB* pVc, IN USHORT usResult, IN USHORT usError );
VOID CloseTdix( IN TUNNELWORK* pWork, IN TUNNELCB* pTunnel, IN VCCB* pVc, IN ULONG_PTR* punpArgs );
VOID CloseTunnel( IN TUNNELWORK* pWork, IN TUNNELCB* pTunnel, IN VCCB* pVc, IN ULONG_PTR* punpArgs );
VOID CloseTunnel2( IN TUNNELCB* pTunnel );
VOID CompleteVcs( IN TUNNELCB* pTunnel );
VOID DeleteHostRoute( IN TUNNELWORK* pWork, IN TUNNELCB* pTunnel, IN VCCB* pVc, IN ULONG_PTR* punpArgs );
VOID DereferenceAdapter( IN ADAPTERCB* pAdapter );
VOID DereferenceCall( IN VCCB* pVc );
LONG DereferenceControlSent( IN CONTROLSENT* pSent );
LONG DereferencePayloadSent( IN PAYLOADSENT* pPs );
VOID DereferenceSap( IN ADAPTERCB* pAdapter );
LONG DereferenceTunnel( IN TUNNELCB* pTunnel );
VOID DereferenceVc( IN VCCB* pVc );
VOID DottedFromIpAddress( IN ULONG ulIpAddress, OUT CHAR* pszIpAddress, IN BOOLEAN fUnicode );
NDIS_STATUS ExecuteWork( IN ADAPTERCB* pAdapter, IN NDIS_PROC pProc, IN PVOID pContext, IN ULONG ulArg1, IN ULONG ulArg2, IN ULONG ulArg3, IN ULONG ulArg4 );
#if 0
VOID ExplodeWanAddress( IN WAN_ADDRESS* pWanAddress, OUT CHAR** ppArg1, OUT ULONG* pulLength1, OUT CHAR** ppArg2, OUT ULONG* pulLength2, OUT CHAR** ppArg3, OUT ULONG* pulLength3 ); #endif
VOID FsmCloseCall( IN TUNNELWORK* pWork, IN TUNNELCB* pTunnel, IN VCCB* pVc, IN ULONG_PTR* punpArgs );
VOID FsmCloseTunnel( IN TUNNELWORK* pWork, IN TUNNELCB* pTunnel, IN VCCB* pVc, IN ULONG_PTR* punpArgs );
VOID FsmOpenCall( IN TUNNELCB* pTunnel, IN VCCB* pVc );
VOID FsmOpenTunnel( IN TUNNELWORK* pWork, IN TUNNELCB* pTunnel, IN VCCB* pVc, IN ULONG_PTR* punpArgs );
VOID FsmOpenIdleTunnel( IN TUNNELCB* pTunnel, IN VCCB* pVc );
BOOLEAN FsmReceive( IN TUNNELCB* pTunnel, IN VCCB* pVc, IN CHAR* pBuffer, IN CONTROLMSGINFO* pControl );
CHAR* GetFullHostNameFromRegistry( VOID );
USHORT GetNextTerminationCallId( IN ADAPTERCB* pAdapter );
USHORT GetNextTunnelId( IN ADAPTERCB* pAdapter );
VOID IndicateLinkStatus( IN VCCB* pVc, IN LINKSTATUSINFO* pInfo );
ULONG IpAddressFromDotted( IN CHAR* pchIpAddress );
NDIS_STATUS LcmCmOpenAf( IN NDIS_HANDLE CallMgrBindingContext, IN PCO_ADDRESS_FAMILY AddressFamily, IN NDIS_HANDLE NdisAfHandle, OUT PNDIS_HANDLE CallMgrAfContext );
NDIS_STATUS LcmCmCloseAf( IN NDIS_HANDLE CallMgrAfContext );
NDIS_STATUS LcmCmRegisterSap( IN NDIS_HANDLE CallMgrAfContext, IN PCO_SAP Sap, IN NDIS_HANDLE NdisSapHandle, OUT PNDIS_HANDLE CallMgrSapContext );
NDIS_STATUS LcmCmDeregisterSap( NDIS_HANDLE CallMgrSapContext );
#ifndef OLDMCM
NDIS_STATUS LcmCmCreateVc( IN NDIS_HANDLE ProtocolAfContext, IN NDIS_HANDLE NdisVcHandle, OUT PNDIS_HANDLE ProtocolVcContext );
NDIS_STATUS LcmCmDeleteVc( IN NDIS_HANDLE ProtocolVcContext );
#endif // !OLDMCM
NDIS_STATUS LcmCmMakeCall( IN NDIS_HANDLE CallMgrVcContext, IN OUT PCO_CALL_PARAMETERS CallParameters, IN NDIS_HANDLE NdisPartyHandle, OUT PNDIS_HANDLE CallMgrPartyContext );
NDIS_STATUS LcmCmCloseCall( IN NDIS_HANDLE CallMgrVcContext, IN NDIS_HANDLE CallMgrPartyContext, IN PVOID CloseData, IN UINT Size );
VOID LcmCmIncomingCallComplete( IN NDIS_STATUS Status, IN NDIS_HANDLE CallMgrVcContext, IN PCO_CALL_PARAMETERS CallParameters );
VOID LcmCmActivateVcComplete( IN NDIS_STATUS Status, IN NDIS_HANDLE CallMgrVcContext, IN PCO_CALL_PARAMETERS CallParameters );
VOID LcmCmDeactivateVcComplete( IN NDIS_STATUS Status, IN NDIS_HANDLE CallMgrVcContext );
NDIS_STATUS LcmCmModifyCallQoS( IN NDIS_HANDLE CallMgrVcContext, IN PCO_CALL_PARAMETERS CallParameters );
NDIS_STATUS LcmCmRequest( IN NDIS_HANDLE CallMgrAfContext, IN NDIS_HANDLE CallMgrVcContext, IN NDIS_HANDLE CallMgrPartyContext, IN OUT PNDIS_REQUEST NdisRequest );
NDIS_STATUS LmpInitialize( OUT PNDIS_STATUS OpenErrorStatus, OUT PUINT SelectedMediumIndex, IN PNDIS_MEDIUM MediumArray, IN UINT MediumArraySize, IN NDIS_HANDLE MiniportAdapterHandle, IN NDIS_HANDLE WrapperConfigurationContext );
VOID LmpHalt( IN NDIS_HANDLE MiniportAdapterContext );
NDIS_STATUS LmpReset( OUT PBOOLEAN AddressingReset, IN NDIS_HANDLE MiniportAdapterContext );
VOID LmpReturnPacket( IN NDIS_HANDLE MiniportAdapterContext, IN PNDIS_PACKET Packet );
NDIS_STATUS LmpQueryInformation( IN NDIS_HANDLE MiniportAdapterContext, IN NDIS_OID Oid, IN PVOID InformationBuffer, IN ULONG InformationBufferLength, OUT PULONG BytesWritten, OUT PULONG BytesNeeded );
NDIS_STATUS LmpSetInformation( IN NDIS_HANDLE MiniportAdapterContext, IN NDIS_OID Oid, IN PVOID InformationBuffer, IN ULONG InformationBufferLength, OUT PULONG BytesRead, OUT PULONG BytesNeeded );
#ifdef OLDMCM
NDIS_STATUS LmpCoCreateVc( IN NDIS_HANDLE MiniportAdapterContext, IN NDIS_HANDLE NdisVcHandle, IN PNDIS_HANDLE MiniportVcContext );
NDIS_STATUS LmpCoDeleteVc( IN NDIS_HANDLE MiniportVcContext );
#endif // OLDMCM
NDIS_STATUS LmpCoActivateVc( IN NDIS_HANDLE MiniportVcContext, IN OUT PCO_CALL_PARAMETERS CallParameters );
NDIS_STATUS LmpCoDeactivateVc( IN NDIS_HANDLE MiniportVcContext );
VOID LmpCoSendPackets( IN NDIS_HANDLE MiniportVcContext, IN PPNDIS_PACKET PacketArray, IN UINT NumberOfPackets );
NDIS_STATUS LmpCoRequest( IN NDIS_HANDLE MiniportAdapterContext, IN NDIS_HANDLE MiniportVcContext, IN OUT PNDIS_REQUEST NdisRequest );
VOID L2tpReceive( IN TDIXCONTEXT* pTdix, IN TDIXRDGINFO* pRdg, IN CHAR* pBuffer, IN ULONG ulOffset, IN ULONG ulBufferLen );
CHAR* MsgTypePszFromUs( IN USHORT usMsgType );
#if READFLAGSDIRECT == 0
ULONG ReadFlags( IN ULONG* pulFlags ); #endif
BOOLEAN ReceiveControlExpected( IN TUNNELCB* pTunnel, IN VCCB* pVc, IN CHAR* pBuffer, IN CONTROLMSGINFO* pControl );
VOID ReferenceAdapter( IN ADAPTERCB* pAdapter );
BOOLEAN ReferenceCall( IN VCCB* pVc );
VOID ReferenceControlSent( IN CONTROLSENT* pSent );
VOID ReferencePayloadSent( IN PAYLOADSENT* pPs );
BOOLEAN ReferenceSap( IN ADAPTERCB* pAdapter );
LONG ReferenceTunnel( IN TUNNELCB* pTunnel, IN BOOLEAN fHaveLockTunnels );
VOID ReferenceVc( IN VCCB* pVc );
BOOLEAN ReleaseCallIdSlot( IN VCCB* pVc );
NDIS_STATUS ReserveCallIdSlot( IN VCCB* pVc );
VOID ResetHelloTimer( IN TUNNELCB* pTunnel );
VOID ScheduleTunnelWork( IN TUNNELCB* pTunnel, IN VCCB* pVc, IN PTUNNELWORK pHandler, IN ULONG_PTR unpArg0, IN ULONG_PTR unpArg1, IN ULONG_PTR unpArg2, IN ULONG_PTR unpArg3, IN BOOLEAN fTcbPreReferenced, IN BOOLEAN fHighPriority );
NDIS_STATUS ScheduleWork( IN ADAPTERCB* pAdapter, IN NDIS_PROC pProc, IN PVOID pContext );
VOID SendControlAck( IN TUNNELWORK* pWork, IN TUNNELCB* pTunnel, IN VCCB* pVc, IN ULONG_PTR* punpArgs );
VOID SendControl( IN TUNNELCB* pTunnel, IN VCCB* pVc, IN USHORT usMsgType, IN ULONG ulBuildAvpsArg1, IN ULONG ulBuildAvpsArg2, IN PVOID pvBuildAvpsArg3, IN ULONG ulFlags );
VOID SendControlTimerEvent( IN TIMERQITEM* pItem, IN VOID* pContext, IN TIMERQEVENT event );
VOID SendPayload( IN VCCB* pVc, IN NDIS_PACKET* pPacket );
VOID SendPayloadAck( IN TUNNELWORK* pWork, IN TUNNELCB* pTunnel, IN VCCB* pVc, IN ULONG_PTR* punpArgs );
VOID SendPending( IN TUNNELWORK* pWork, IN TUNNELCB* pTunnel, IN VCCB* pVc, IN ULONG_PTR* punpArgs );
VOID SetFlags( IN OUT ULONG* pulFlags, IN ULONG ulMask );
TUNNELCB* SetupTunnel( IN ADAPTERCB* pAdapter, IN ULONG ulIpAddress, IN USHORT usUdpPort, IN USHORT usAssignedTunnelId, IN BOOLEAN fExclusive );
VOID SetupVcAsynchronously( IN TUNNELCB* pTunnel, IN ULONG ulIpAddress, IN CHAR* pBuffer, IN CONTROLMSGINFO* pControl );
WCHAR* StrDupAsciiToUnicode( IN CHAR* psz, IN ULONG ulPszBytes );
WCHAR* StrDupNdisString( IN NDIS_STRING* pNdisString );
CHAR* StrDupNdisVarDataDescStringA( IN NDIS_VAR_DATA_DESC* pDesc );
CHAR* StrDupNdisVarDataDescStringToA( IN NDIS_VAR_DATA_DESC UNALIGNED* pDesc );
CHAR* StrDupNdisStringToA( IN NDIS_STRING* pNdisString );
CHAR* StrDupSized( IN CHAR* psz, IN ULONG ulLength, IN ULONG ulExtra );
CHAR* StrDupUnicodeToAscii( IN WCHAR* pwsz, IN ULONG ulPwszBytes );
ULONG StrLenW( IN WCHAR* psz );
VOID TransferLinkStatusInfo( IN VCCB* pVc, OUT LINKSTATUSINFO* pInfo );
TUNNELCB* TunnelCbFromIpAddressAndAssignedTunnelId( IN ADAPTERCB* pAdapter, IN ULONG ulIpAddress, IN USHORT usUdpPort, IN USHORT usAssignedTunnelId );
VOID TunnelTransitionComplete( IN TUNNELCB* pTunnel, IN L2TPCCSTATE state );
VOID UpdateGlobalCallStats( IN VCCB* pVc );
VCCB* VcCbFromCallId( IN TUNNELCB* pTunnel, IN USHORT usCallId );
#endif // _L2TPP_H_
|