Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

3020 lines
82 KiB

/********************************************************************/
/** Copyright(c) 1989 Microsoft Corporation. **/
/********************************************************************/
//***
//
// Filename: worker.c
//
// Description: This module contains code for the worker thread.
//
// History:
// Nov 11,1993. NarenG Created original version.
// Jan 09,1995 RamC Close hToken in ProcessLineDownWorker()
// routine to release the RAS license.
//
// Tab Stop = 8
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h> // needed for winbase.h
#include <windows.h> // Win32 base API's
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include <ntlsapi.h>
#include <lmcons.h>
#include <mprlog.h>
#include <raserror.h>
#include <mprerror.h>
#include <rasman.h>
#include <rtutils.h>
#include <rasppp.h>
#include <pppcp.h>
#include <ppp.h>
#include <smaction.h>
#include <smevents.h>
#include <receive.h>
#include <auth.h>
#include <callback.h>
#include <init.h>
#include <lcp.h>
#include <timer.h>
#include <util.h>
#include <worker.h>
#include <bap.h>
#include <rassrvr.h>
#define INCL_RASAUTHATTRIBUTES
#define INCL_PWUTIL
#include <ppputil.h>
//**
//
// Call: WorkerThread
//
// Returns: NO_ERROR
//
// Description: This thread will wait for an item in the WorkItemQ and then
// will process it. This will happen in a never-ending loop.
//
#if _MSC_FULL_VER >= 13008827
#pragma warning(push)
#pragma warning(disable:4715) // Not all control paths return (due to infinite loop)
#endif
DWORD
WorkerThread(
IN LPVOID pThreadParameter
)
{
PCB_WORK_ITEM * pWorkItem = (PCB_WORK_ITEM*)NULL;
DWORD dwTimeToSleepFor = INFINITE;
HINSTANCE hInstance;
HANDLE hEvents[3];
DWORD dwSignaledEvent;
DWORD dwTimeBeforeWait;
DWORD dwTimeElapsed;
BOOL fTimerQEmpty = TRUE;
hEvents[0] = WorkItemQ.hEventNonEmpty;
hEvents[1] = TimerQ.hEventNonEmpty;
hEvents[2] = PppConfigInfo.hEventChangeNotification;
RegNotifyChangeKeyValue( PppConfigInfo.hKeyPpp,
TRUE,
REG_NOTIFY_CHANGE_LAST_SET,
PppConfigInfo.hEventChangeNotification,
TRUE );
for(;;)
{
dwTimeBeforeWait = GetCurrentTime();
//
// Wait for work to do
//
dwSignaledEvent = WaitForMultipleObjectsEx(
3,
hEvents,
FALSE,
dwTimeToSleepFor,
TRUE );
switch( dwSignaledEvent )
{
case 0:
//
// Take Mutex around work event Q
//
EnterCriticalSection( &(WorkItemQ.CriticalSection) );
//
// Remove the first item
//
PPP_ASSERT( WorkItemQ.pQHead != (PCB_WORK_ITEM*)NULL );
pWorkItem = WorkItemQ.pQHead;
WorkItemQ.pQHead = pWorkItem->pNext;
if ( WorkItemQ.pQHead == (PCB_WORK_ITEM*)NULL )
{
ResetEvent( WorkItemQ.hEventNonEmpty );
WorkItemQ.pQTail = (PCB_WORK_ITEM *)NULL;
}
LeaveCriticalSection( &(WorkItemQ.CriticalSection) );
pWorkItem->Process( pWorkItem );
//
// Zero out work item since it may have contained the password
//
ZeroMemory( pWorkItem, sizeof( PCB_WORK_ITEM ) );
LOCAL_FREE( pWorkItem );
break;
case WAIT_TIMEOUT:
TimerTick( &fTimerQEmpty );
dwTimeToSleepFor = fTimerQEmpty ? INFINITE : 1000;
continue;
case 1:
fTimerQEmpty = FALSE;
break;
case 2:
//
// Process change notification event
//
ProcessChangeNotification( NULL );
RegNotifyChangeKeyValue(
PppConfigInfo.hKeyPpp,
TRUE,
REG_NOTIFY_CHANGE_LAST_SET,
PppConfigInfo.hEventChangeNotification,
TRUE );
break;
case WAIT_IO_COMPLETION:
break;
default:
PPP_ASSERT( FALSE );
}
if ( !fTimerQEmpty )
{
if ( dwTimeToSleepFor == INFINITE )
{
dwTimeToSleepFor = 1000;
}
else
{
//
// We did not get a timeout but do we need to call the timer?
// Has over a second passed since we called the TimerQTick?
//
dwTimeElapsed =
( GetCurrentTime() >= dwTimeBeforeWait )
? GetCurrentTime() - dwTimeBeforeWait
: GetCurrentTime() + (0xFFFFFFFF - dwTimeBeforeWait);
if ( dwTimeElapsed >= dwTimeToSleepFor )
{
TimerTick( &fTimerQEmpty );
dwTimeToSleepFor = fTimerQEmpty ? INFINITE : 1000;
}
else
{
dwTimeToSleepFor -= dwTimeElapsed;
}
}
}
}
return( NO_ERROR );
}
#if _MSC_FULL_VER >= 13008827
#pragma warning(pop)
#endif
//**
//
// Call: ProcessLineUpWorker
//
// Returns: None
//
// Description: Will do the actual processing of the line up event.
//
//
VOID
ProcessLineUpWorker(
IN PCB_WORK_ITEM * pWorkItem,
IN BOOL fThisIsACallback
)
{
DWORD dwRetCode;
DWORD dwLength;
DWORD dwComputerNameLen;
DWORD dwIndex;
PCB * pNewPcb = NULL;
RASMAN_INFO RasmanInfo;
DWORD dwError;
BOOL fSuccess = FALSE;
do
{
PppLog( 1, "Line up event occurred on port %d", pWorkItem->hPort );
pNewPcb = GetPCBPointerFromhPort( pWorkItem->hPort );
if ( NULL == pNewPcb )
{
//
// Allocate and initialize pNewPcb
//
pNewPcb = (PCB *)LOCAL_ALLOC( LPTR, sizeof( PCB ) );
if ( pNewPcb == (PCB *)NULL )
{
//
// Tell the owner of the port that we failed to open it.
//
NotifyCallerOfFailureOnPort(
pWorkItem->hPort,
pWorkItem->fServer,
GetLastError() );
break;
}
}
else
{
if (!( pNewPcb->fFlags & PCBFLAG_PORT_IN_LISTENING_STATE ))
{
PppLog( 1, "Line up on port %d without a line down!",
pWorkItem->hPort );
return;
}
//
// We will put it back in the table later
//
RemovePcbFromTable( pNewPcb );
}
if ( !pWorkItem->fServer )
{
if ( !(pWorkItem->PppMsg.Start.ConfigInfo.dwConfigMask &
( PPPCFG_ProjectNbf
| PPPCFG_ProjectIp
| PPPCFG_ProjectIpx
| PPPCFG_ProjectAt ) ) )
{
NotifyCallerOfFailureOnPort( pWorkItem->hPort,
pWorkItem->fServer,
ERROR_PPP_NO_PROTOCOLS_CONFIGURED);
break;
}
}
//
// Get Rasman info for this port. We need this to get the devicetype
// and BAP
//
dwError = RasGetInfo( NULL, pWorkItem->hPort, &RasmanInfo );
if ( NO_ERROR != dwError )
{
PppLog(1,"RasGetInfo failed and returned returned %d", dwError);
break;
}
pNewPcb->pSendBuf = (PPP_PACKET*)NULL;
pNewPcb->hPort = pWorkItem->hPort;
pNewPcb->pNext = (PCB*)NULL;
pNewPcb->UId = 0;
pNewPcb->dwPortId = GetNewPortOrBundleId();
pNewPcb->RestartTimer = CalculateRestartTimer( pWorkItem->hPort );
pNewPcb->PppPhase = PPP_LCP;
pNewPcb->fFlags |= pWorkItem->fServer ? PCBFLAG_IS_SERVER:0;
pNewPcb->fFlags |= fThisIsACallback
? PCBFLAG_THIS_IS_A_CALLBACK
: 0;
pNewPcb->pUserAttributes = NULL;
pNewPcb->pAuthenticatorAttributes = NULL;
pNewPcb->pAuthProtocolAttributes = NULL;
pNewPcb->pAccountingAttributes = NULL;
pNewPcb->dwOutstandingAuthRequestId = 0xFFFFFFFF;
pNewPcb->dwDeviceType = RasmanInfo.RI_rdtDeviceType;
GetSystemTimeAsFileTime( (FILETIME*)&(pNewPcb->qwActiveTime) );
if ( NULL == pNewPcb->pBcb )
{
if ( ( dwRetCode = AllocateAndInitBcb( pNewPcb ) ) != NO_ERROR )
{
NotifyCallerOfFailureOnPort(
pWorkItem->hPort,
pWorkItem->fServer,
dwRetCode );
break;
}
}
dwRetCode = RasPortGetBundle(NULL,
pNewPcb->hPort,
&(pNewPcb->pBcb->hConnection) );
if ( dwRetCode != NO_ERROR )
{
NotifyCallerOfFailureOnPort(
pWorkItem->hPort,
pWorkItem->fServer,
dwRetCode );
break;
}
pNewPcb->pBcb->fFlags |= pWorkItem->fServer ? BCBFLAG_IS_SERVER:0;
pNewPcb->pBcb->szRemoteUserName[0] = (CHAR)NULL;
pNewPcb->pBcb->szRemoteDomain[0] = (CHAR)NULL;
pNewPcb->pBcb->szOldPassword[0] = '\0';
if ( pNewPcb->fFlags & PCBFLAG_IS_SERVER )
{
pNewPcb->dwEapTypeToBeUsed = 0xFFFFFFFF;
pNewPcb->fCallbackPrivilege = RASPRIV_NoCallback;
pNewPcb->pBcb->hTokenImpersonateUser= INVALID_HANDLE_VALUE;
pNewPcb->dwAuthRetries = ( fThisIsACallback )
? 0
: pWorkItem->PppMsg.DdmStart.dwAuthRetries;
if ( fThisIsACallback )
{
strcpy( pNewPcb->szCallbackNumber,
pWorkItem->PppMsg.CallbackDone.szCallbackNumber );
}
else
{
strcpy( pNewPcb->szPortName,
pWorkItem->PppMsg.DdmStart.szPortName );
PppLog( 1, "PortName: %s", pNewPcb->szPortName );
}
ZeroMemory( &(pNewPcb->ConfigInfo), sizeof( pNewPcb->ConfigInfo ) );
ZeroMemory( &(pNewPcb->Luid), sizeof( LUID ) );
pNewPcb->pBcb->szComputerName[0] = (CHAR)NULL;
pNewPcb->ConfigInfo = PppConfigInfo.ServerConfigInfo;
pNewPcb->dwAutoDisconnectTime = 0;
pNewPcb->pBcb->szLocalUserName[0] = (CHAR)NULL;
pNewPcb->pBcb->szLocalDomain[0] = (CHAR)NULL;
pNewPcb->pBcb->szPassword[0] = (CHAR)NULL;
pNewPcb->pBcb->fFlags |= BCBFLAG_CAN_ACCEPT_CALLS;
pNewPcb->pBcb->BapCb.szServerPhoneNumber =
LocalAlloc( LPTR, sizeof(CHAR) * (RAS_MaxCallbackNumber + 1) );
if ( NULL == pNewPcb->pBcb->BapCb.szServerPhoneNumber )
{
dwRetCode = GetLastError();
NotifyCallerOfFailureOnPort(
pWorkItem->hPort,
TRUE,
dwRetCode );
break;
}
pNewPcb->pBcb->BapCb.szClientPhoneNumber =
LocalAlloc( LPTR, sizeof(CHAR) * (RAS_MaxCallbackNumber + 1) );
if ( NULL == pNewPcb->pBcb->BapCb.szClientPhoneNumber )
{
dwRetCode = GetLastError();
NotifyCallerOfFailureOnPort(
pWorkItem->hPort,
TRUE,
dwRetCode );
break;
}
if ( GetCpIndexFromProtocol( PPP_BACP_PROTOCOL ) == (DWORD)-1 )
{
PppConfigInfo.ServerConfigInfo.dwConfigMask &=
~PPPCFG_NegotiateBacp;
}
if ( PppConfigInfo.ServerConfigInfo.dwConfigMask &
PPPCFG_NegotiateBacp)
{
//
// We won't check for successful return from this function.
// If it fails, szServerPhoneNumber will remain an empty string.
//
FGetOurPhoneNumberFromHPort(
pNewPcb->hPort,
pNewPcb->pBcb->BapCb.szServerPhoneNumber);
}
pNewPcb->pUserAttributes = GetUserAttributes( pNewPcb );
}
else
{
DWORD cbPassword;
PBYTE pbPassword = NULL;
pNewPcb->dwEapTypeToBeUsed = pWorkItem->PppMsg.Start.dwEapTypeId;
pNewPcb->pBcb->hTokenImpersonateUser =
pWorkItem->PppMsg.Start.hToken;
pNewPcb->pBcb->pCustomAuthConnData =
pWorkItem->PppMsg.Start.pCustomAuthConnData;
pNewPcb->pBcb->pCustomAuthUserData =
pWorkItem->PppMsg.Start.pCustomAuthUserData;
//
// EapUIData.pEapUIData is allocated by rasman and freed by engine.
// raseap.c must not free it.
//
pNewPcb->pBcb->EapUIData =
pWorkItem->PppMsg.Start.EapUIData;
if (pWorkItem->PppMsg.Start.fLogon)
{
pNewPcb->pBcb->fFlags |= BCBFLAG_LOGON_USER_DATA;
}
if (pWorkItem->PppMsg.Start.fNonInteractive)
{
pNewPcb->fFlags |= PCBFLAG_NON_INTERACTIVE;
}
if (pWorkItem->PppMsg.Start.dwFlags & PPPFLAGS_DisableNetbt)
{
pNewPcb->fFlags |= PCBFLAG_DISABLE_NETBT;
}
//
// We do this to get the sub entry index, which is required by BAP.
// If this function fails, BAP will think that the sub entry is not
// connected. BAP will not work correctly, but nothing very bad will
// happen.
//
pNewPcb->dwSubEntryIndex = RasmanInfo.RI_SubEntry;
pNewPcb->dwAuthRetries = 0;
strcpy( pNewPcb->pBcb->szLocalUserName,
pWorkItem->PppMsg.Start.szUserName );
// DecodePw( pWorkItem->PppMsg.Start.chSeed, pWorkItem->PppMsg.Start.szPassword );
// strcpy( pNewPcb->pBcb->szPassword,
// pWorkItem->PppMsg.Start.szPassword );
CopyMemory(&pNewPcb->pBcb->DBPassword,
&pWorkItem->PppMsg.Start.DBPassword,
sizeof(DATA_BLOB));
ZeroMemory(&pWorkItem->PppMsg.Start.DBPassword,
sizeof(DATA_BLOB));
// EncodePw( pWorkItem->PppMsg.Start.chSeed, pWorkItem->PppMsg.Start.szPassword );
// EncodePw( pNewPcb->pBcb->chSeed, pNewPcb->pBcb->szPassword );
strcpy( pNewPcb->pBcb->szLocalDomain,
pWorkItem->PppMsg.Start.szDomain );
pNewPcb->Luid = pWorkItem->PppMsg.Start.Luid;
pNewPcb->ConfigInfo = pWorkItem->PppMsg.Start.ConfigInfo;
pNewPcb->dwAutoDisconnectTime
= pWorkItem->PppMsg.Start.dwAutoDisconnectTime;
//Set the LCPEchoTimeout here
pNewPcb->dwLCPEchoTimeInterval = PppConfigInfo.dwLCPEchoTimeInterval; //Time interval between LCP echos
pNewPcb->dwIdleBeforeEcho = PppConfigInfo.dwIdleBeforeEcho; //Idle time before the LCP echo begins
pNewPcb->dwNumMissedEchosBeforeDisconnect = PppConfigInfo.dwNumMissedEchosBeforeDisconnect; //Num missed echos before disconnect
CopyMemory( pNewPcb->pBcb->InterfaceInfo.szzParameters,
pWorkItem->PppMsg.Start.szzParameters,
sizeof( pNewPcb->pBcb->InterfaceInfo.szzParameters ));
GetLocalComputerName( pNewPcb->pBcb->szComputerName );
strcpy( pNewPcb->szPortName, pWorkItem->PppMsg.Start.szPortName );
PppLog(1,"PortName: %s", pNewPcb->szPortName);
PPP_ASSERT( NULL == pNewPcb->pBcb->szPhonebookPath );
PPP_ASSERT( NULL == pNewPcb->pBcb->szEntryName );
PPP_ASSERT( NULL == pNewPcb->pBcb->BapCb.szServerPhoneNumber );
pNewPcb->pBcb->szPhonebookPath
= pWorkItem->PppMsg.Start.pszPhonebookPath;
pNewPcb->pBcb->szEntryName = pWorkItem->PppMsg.Start.pszEntryName;
//
// pszPhoneNumber will have the originally dialed number, even if
// this is a callback.
//
pNewPcb->pBcb->BapCb.szServerPhoneNumber
= pWorkItem->PppMsg.Start.pszPhoneNumber;
RemoveNonNumerals(pNewPcb->pBcb->BapCb.szServerPhoneNumber);
pNewPcb->pBcb->BapParams = pWorkItem->PppMsg.Start.BapParams;
pNewPcb->pBcb->fFlags |= BCBFLAG_CAN_ACCEPT_CALLS;
pNewPcb->pBcb->fFlags |= BCBFLAG_CAN_CALL;
if ( pNewPcb->ConfigInfo.dwConfigMask & PPPCFG_NoCallback )
{
pNewPcb->pBcb->fFlags &= ~BCBFLAG_CAN_ACCEPT_CALLS;
}
if ( pWorkItem->PppMsg.Start.PppInterfaceInfo.IfType == (DWORD)-1 )
{
pNewPcb->pBcb->InterfaceInfo.IfType = (DWORD)-1;
pNewPcb->pBcb->InterfaceInfo.hIPInterface= INVALID_HANDLE_VALUE;
pNewPcb->pBcb->InterfaceInfo.hIPXInterface
= INVALID_HANDLE_VALUE;
}
else
{
pNewPcb->pBcb->InterfaceInfo =
pWorkItem->PppMsg.Start.PppInterfaceInfo;
//
// If we are a router dialing out and fRedialOnLinkFailure is
// set that means that we are a persistent interface so set
// Idle-Disconnect time to 0.
//
if ( pNewPcb->pBcb->InterfaceInfo.IfType
== ROUTER_IF_TYPE_FULL_ROUTER )
{
if ( pWorkItem->PppMsg.Start.fRedialOnLinkFailure )
{
pNewPcb->dwAutoDisconnectTime = 0;
}
lstrcpy( pNewPcb->pBcb->szRemoteUserName,
pNewPcb->pBcb->szEntryName );
if (pNewPcb->ConfigInfo.dwConfigMask &
PPPCFG_AuthenticatePeer)
{
pNewPcb->pUserAttributes = GetUserAttributes( pNewPcb );
}
}
}
if ( pNewPcb->pBcb->InterfaceInfo.IfType
!= ROUTER_IF_TYPE_FULL_ROUTER )
{
//
// We want HKEY_CURRENT_USER to represent the logged on user,
// not the service.
//
// What about the asynchronous RasDial case? Is it
// possible that the process represented by dwPid is now gone?
// Will it help if you use ImpersonateLoggedOnUser() to get
// callback numbers?
pNewPcb->pBcb->szTextualSid =
TextualSidFromPid( pWorkItem->PppMsg.Start.dwPid );
}
if ( GetCpIndexFromProtocol( PPP_BACP_PROTOCOL ) == (DWORD)-1 )
{
pNewPcb->ConfigInfo.dwConfigMask &= ~PPPCFG_NegotiateBacp;
}
}
PppLog( 2, "Starting PPP on link with IfType=0x%x,IPIf=0x%x,IPXIf=0x%x",
pNewPcb->pBcb->InterfaceInfo.IfType,
pNewPcb->pBcb->InterfaceInfo.hIPInterface,
pNewPcb->pBcb->InterfaceInfo.hIPXInterface );
//
// Allocate bundle block for this port
//
dwLength = LCP_DEFAULT_MRU;
dwRetCode = RasGetBuffer((CHAR**)&(pNewPcb->pSendBuf), &dwLength );
if ( dwRetCode != NO_ERROR )
{
NotifyCallerOfFailure( pNewPcb, dwRetCode );
break;
}
PppLog( 2, "RasGetBuffer returned %x for SendBuf", pNewPcb->pSendBuf);
//
// Initialize LCP and all the NCPs
//
pNewPcb->LcpCb.fConfigurable = TRUE;
if ( !( FsmInit( pNewPcb, LCP_INDEX ) ) )
{
NotifyCallerOfFailure( pNewPcb, pNewPcb->LcpCb.dwError );
break;
}
//
// Ask RasMan to do RasPortReceive
//
dwRetCode = RasPppStarted( pNewPcb->hPort );
if ( dwRetCode != NO_ERROR )
{
NotifyCallerOfFailure( pNewPcb, dwRetCode );
break;
}
fSuccess = TRUE;
//
// Insert NewPcb into PCB hash table
//
dwIndex = HashPortToBucket( pWorkItem->hPort );
PppLog( 2, "Inserting port in bucket # %d", dwIndex );
pNewPcb->pNext = PcbTable.PcbBuckets[dwIndex].pPorts;
PcbTable.PcbBuckets[dwIndex].pPorts = pNewPcb;
//
// Insert NewPcb's BCB into BCB hash table
//
dwIndex = HashPortToBucket( pNewPcb->pBcb->hConnection );
PppLog( 2, "Inserting bundle in bucket # %d", dwIndex );
pNewPcb->pBcb->pNext = PcbTable.BcbBuckets[dwIndex].pBundles;
PcbTable.BcbBuckets[dwIndex].pBundles = pNewPcb->pBcb;
//
// Initialize the error as no response. If and when the first
// REQ/ACK/NAK/REJ comes in we reset this to NO_ERROR
//
pNewPcb->LcpCb.dwError = ERROR_PPP_NO_RESPONSE;
//
// Start the LCP state machine.
//
FsmOpen( pNewPcb, LCP_INDEX );
FsmUp( pNewPcb, LCP_INDEX );
//
// Start NegotiateTimer.
//
if ( PppConfigInfo.NegotiateTime > 0 )
{
InsertInTimerQ( pNewPcb->dwPortId,
pNewPcb->hPort,
0,
0,
FALSE,
TIMER_EVENT_NEGOTIATETIME,
PppConfigInfo.NegotiateTime );
}
//
// If this is the server and this is not a callback line up, then we
// receive the first frame in the call
//
if ( ( pNewPcb->fFlags & PCBFLAG_IS_SERVER ) && ( !fThisIsACallback ) )
{
PPP_PACKET * pPacket;
if ( pNewPcb->LcpCb.dwError == ERROR_PPP_NO_RESPONSE )
{
pNewPcb->LcpCb.dwError = NO_ERROR;
}
//
// Skip over the frame header and check if this is an LCP packet
//
pPacket=(PPP_PACKET*)(pWorkItem->PppMsg.DdmStart.achFirstFrame+12);
if ( WireToHostFormat16( pPacket->Protocol ) == PPP_LCP_PROTOCOL )
{
ReceiveViaParser(
pNewPcb,
pPacket,
pWorkItem->PppMsg.DdmStart.cbFirstFrame - 12 );
}
}
}
while ( FALSE );
if ( !fSuccess )
{
if ( !pWorkItem->fServer )
{
if ( INVALID_HANDLE_VALUE != pWorkItem->PppMsg.Start.hToken )
{
CloseHandle( pWorkItem->PppMsg.Start.hToken );
}
LocalFree( pWorkItem->PppMsg.Start.pCustomAuthConnData );
LocalFree( pWorkItem->PppMsg.Start.pCustomAuthUserData );
LocalFree( pWorkItem->PppMsg.Start.EapUIData.pEapUIData );
LocalFree( pWorkItem->PppMsg.Start.pszPhonebookPath );
LocalFree( pWorkItem->PppMsg.Start.pszEntryName );
LocalFree( pWorkItem->PppMsg.Start.pszPhoneNumber );
if ( ( NULL != pNewPcb )
&& ( NULL != pNewPcb->pBcb ) )
{
//
// Do not LocalFree or CloseHandle twice
//
pNewPcb->pBcb->hTokenImpersonateUser = INVALID_HANDLE_VALUE;
pNewPcb->pBcb->pCustomAuthConnData = NULL;
pNewPcb->pBcb->pCustomAuthUserData = NULL;
pNewPcb->pBcb->EapUIData.pEapUIData = NULL;
pNewPcb->pBcb->szPhonebookPath = NULL;
pNewPcb->pBcb->szEntryName = NULL;
pNewPcb->pBcb->BapCb.szServerPhoneNumber = NULL;
}
}
if ( NULL != pNewPcb )
{
DeallocateAndRemoveBcbFromTable( pNewPcb->pBcb );
if ( NULL != pNewPcb->pSendBuf )
{
RasFreeBuffer( (CHAR*)(pNewPcb->pSendBuf) );
}
LOCAL_FREE( pNewPcb );
}
}
}
//**
//
// Call: ProcessLineUp
//
// Returns: None
//
// Description: Called to process a line up event.
//
VOID
ProcessLineUp(
IN PCB_WORK_ITEM * pWorkItem
)
{
ProcessLineUpWorker( pWorkItem,
( pWorkItem->fServer )
? FALSE
: pWorkItem->PppMsg.Start.fThisIsACallback );
}
//**
//
// Call: ProcessPostLineDown
//
// Returns: None.
//
// Description: Handles Post Line Down cleanup only in the case accounting is setup.
// see Whistler BUG:174822
//
VOID
ProcessPostLineDown(
IN PCB_WORK_ITEM * pWorkItem
)
{
//This function will be always called as a result of
//postlinedown message. So get the pcb from the work item directly.
PCB * pPcb = (PCB *)pWorkItem->PppMsg.PostLineDown.pPcb;
if ( pPcb == (PCB*)NULL )
{
PppLog( 1, "PostLineDown: PCB not found in post line down! Port = %d", pWorkItem->hPort );
return;
}
PostLineDownWorker(pPcb);
}
VOID
PostLineDownWorker(
PCB * pPcb
)
{
PppLog( 1, "Post line down event occurred on port %d", pPcb->hPort );
if ( !( pPcb->fFlags & PCBFLAG_DOING_CALLBACK ) )
{
NotifyCaller( pPcb, PPPDDMMSG_PortCleanedUp, NULL );
}
else
{
if ( !(pPcb->fFlags & PCBFLAG_IS_SERVER ) )
{
//
// If we get here and this flag is sent then we have not sent
// the callback message to the client, hence we send it now.
//
NotifyCaller( pPcb, PPPMSG_Callback, NULL );
}
}
if ( !(pPcb->fFlags & PCBFLAG_IS_SERVER )
&& !(pPcb->fFlags & PCBFLAG_STOPPED_MSG_SENT) )
{
DWORD dwError = 0;
NotifyCaller( pPcb, PPPMSG_Stopped, &dwError );
}
if ( pPcb->fFlags & PCBFLAG_PORT_IN_LISTENING_STATE )
{
//
// This flag is set in FListenForCall in bap.c
//
NotifyCallerOfFailure( pPcb, NO_ERROR );
}
LOCAL_FREE( pPcb );
}
//**
//
// Call: ProcessLineDownWorker
//
// Returns: None.
//
// Description: Handles a line down event. Will remove and deallocate all
// resources associated with the port control block.
//
VOID
ProcessLineDownWorker(
IN PCB_WORK_ITEM * pWorkItem,
BOOL * pfFinalStage
)
{
DWORD dwIndex = HashPortToBucket( pWorkItem->hPort );
PCB * pPcb = GetPCBPointerFromhPort( pWorkItem->hPort );
LCPCB * pLcpCb;
DWORD dwForIndex;
DWORD dwErr;
*pfFinalStage = TRUE;
PppLog( 1, "Line down event occurred on port %d", pWorkItem->hPort );
//
// If the port is already deleted then simply return.
//
if ( pPcb == (PCB*)NULL )
{
PppLog( 1, "PCB not found for port %d!", pWorkItem->hPort );
*pfFinalStage = FALSE;
return;
}
//
// pPcb->pBcb may be NULL if the pPcb was allocated in FListenForCall and it
// did not go thru ProcessLineUpWorker or ProcessRasPortListenEvent,
// which is impossible. I have seen this happen once, when before the
// server had a chance to call back, I hung up the connection, and
// ProcessStopPPP sent a line down to all ports.
//
if ( pPcb->pBcb == (BCB*)NULL )
{
RemovePcbFromTable( pPcb );
NotifyCaller( pPcb, PPPDDMMSG_PortCleanedUp, NULL );
*pfFinalStage = FALSE;
return;
}
//
// Remove PCB from table
// Important Note: Not removing this at this point in time can cause
// a lot of grief!
RemovePcbFromTable( pPcb );
//
// Cancel outstanding receive
//
RasPortCancelReceive( pPcb->hPort );
FsmDown( pPcb, LCP_INDEX );
//
// Remove Auto-Disconnect and high level timer event from the timer Q
//
RemoveFromTimerQ( pPcb->dwPortId,
0,
0,
FALSE,
TIMER_EVENT_NEGOTIATETIME );
RemoveFromTimerQ( pPcb->dwPortId,
0,
0,
FALSE,
TIMER_EVENT_LCP_ECHO );
RemoveFromTimerQ( pPcb->dwPortId,
0,
0,
FALSE,
TIMER_EVENT_HANGUP
);
RemoveFromTimerQ( pPcb->dwPortId,
0,
0,
FALSE,
TIMER_EVENT_AUTODISCONNECT
);
if ( pPcb->fFlags & PCBFLAG_IS_SERVER )
{
RemoveFromTimerQ( pPcb->dwPortId,
0,
0,
FALSE,
TIMER_EVENT_SESSION_TIMEOUT );
}
//
// Make stop accounting call. Need to make this call before unbundling
// because we need to send some mulitlink information.
//
if ( pPcb->pAccountingAttributes != NULL )
{
RemoveFromTimerQ( pPcb->dwPortId,
0,
0,
FALSE,
TIMER_EVENT_INTERIM_ACCOUNTING );
MakeStopOrInterimAccountingCall( pPcb, FALSE );
}
if ( pPcb->fFlags & PCBFLAG_CONNECTION_LOGGED )
{
LPSTR lpsSubStringArray[5];
lpsSubStringArray[0] = pPcb->pBcb->szEntryName;
lpsSubStringArray[1] = pPcb->pBcb->szLocalUserName;
lpsSubStringArray[2] = pPcb->szPortName;
PppLogInformation(ROUTERLOG_DISCONNECTION_OCCURRED,3,lpsSubStringArray);
}
//
// Close all CPs if this is the last port in the bundle if it is bundled,
// or if it was not bundled.
//
if ( ( ( pPcb->fFlags & PCBFLAG_IS_BUNDLED ) &&
( pPcb->pBcb->dwLinkCount == 1 ) )
||
( !(pPcb->fFlags & PCBFLAG_IS_BUNDLED) ) )
{
for(dwIndex=LCP_INDEX+1;dwIndex<PppConfigInfo.NumberOfCPs;dwIndex++)
{
CPCB * pCpCb = GetPointerToCPCB( pPcb, dwIndex );
if ( ( NULL != pCpCb )
&& ( pCpCb->fBeginCalled == TRUE ) )
{
if ( pCpCb->pWorkBuf != NULL )
{
(CpTable[dwIndex].CpInfo.RasCpEnd)( pCpCb->pWorkBuf );
pCpCb->pWorkBuf = NULL;
}
pCpCb->fBeginCalled = FALSE;
}
}
if ( pPcb->pBcb != NULL )
{
//
// Take care of the RAS server policy on workstation
//
if ( pPcb->pBcb->fFlags & BCBFLAG_WKSTA_IN )
{
if ( pPcb->dwDeviceType & RDT_Tunnel )
{
PppConfigInfo.fFlags &= ~PPPCONFIG_FLAG_TUNNEL;
}
else if ( pPcb->dwDeviceType & RDT_Direct )
{
PppConfigInfo.fFlags &= ~PPPCONFIG_FLAG_DIRECT;
}
else
{
PppConfigInfo.fFlags &= ~PPPCONFIG_FLAG_DIALUP;
}
}
DeallocateAndRemoveBcbFromTable( pPcb->pBcb );
}
}
else if ( ( pPcb->fFlags & PCBFLAG_IS_BUNDLED ) &&
( pPcb->pBcb->dwLinkCount > 1 ) )
{
if ( pPcb->pBcb->fFlags & BCBFLAG_CAN_DO_BAP )
{
//
// Reset the start time for the sample period. Now that the
// bandwidth has changed, ndiswan shouldn't ask us to bring
// links up or down based on what happened in the past.
//
BapSetPolicy( pPcb->pBcb );
}
pPcb->pBcb->dwLinkCount--;
for ( dwForIndex = 0;
dwForIndex < pPcb->pBcb->dwPpcbArraySize;
dwForIndex++)
{
if ( pPcb->pBcb->ppPcb[dwForIndex] == pPcb )
{
pPcb->pBcb->ppPcb[dwForIndex] = NULL;
break;
}
}
if ( dwForIndex == pPcb->pBcb->dwPpcbArraySize )
{
PppLog( 1, "There is no back pointer to this PCB!!");
}
}
//
// Close the Aps.
//
pLcpCb = (LCPCB*)(pPcb->LcpCb.pWorkBuf);
if ( pLcpCb != NULL)
{
dwIndex = GetCpIndexFromProtocol( pLcpCb->Local.Work.AP );
if ( dwIndex != (DWORD)-1 )
{
ApStop( pPcb, dwIndex, TRUE );
}
dwIndex = GetCpIndexFromProtocol( pLcpCb->Remote.Work.AP );
if ( dwIndex != (DWORD)-1 )
{
ApStop( pPcb, dwIndex, FALSE );
}
//
// Close CBCP
//
dwIndex = GetCpIndexFromProtocol( PPP_CBCP_PROTOCOL );
if ( dwIndex != (DWORD)-1 )
{
CbStop( pPcb, dwIndex );
}
//
// Close LCP
//
(CpTable[LCP_INDEX].CpInfo.RasCpEnd)(pPcb->LcpCb.pWorkBuf);
pPcb->LcpCb.pWorkBuf = NULL;
}
if ( pPcb->pSendBuf != (PPP_PACKET*)NULL )
{
RasFreeBuffer( (CHAR*)(pPcb->pSendBuf) );
}
if ( pPcb->pUserAttributes != NULL )
{
RasAuthAttributeDestroy( pPcb->pUserAttributes );
pPcb->pUserAttributes = NULL;
}
if ( pPcb->pAuthenticatorAttributes != NULL )
{
PppConfigInfo.RasAuthProviderFreeAttributes(
pPcb->pAuthenticatorAttributes );
pPcb->pAuthenticatorAttributes = NULL;
}
//
// Notify the server that the port is now cleaned up
//
// if accounting is turned on, do not notify the DDM that
// we are done as yet. But do it in post clenup
//moved to post line down
/*
if ( !( pPcb->fFlags & PCBFLAG_DOING_CALLBACK ) )
{
if (
NotifyCaller( pPcb, PPPDDMMSG_PortCleanedUp, NULL );
}
else
{
if ( !(pPcb->fFlags & PCBFLAG_IS_SERVER ) )
{
//
// If we get here and this flag is sent then we have not sent
// the callback message to the client, hence we send it now.
//
NotifyCaller( pPcb, PPPMSG_Callback, NULL );
}
}
*/
//
// Send PPPMSG_Stopped to rasman, if we haven't already. If we get a
// PPPEMSG_Stop and then a PPPEMSG_LineDown before we call ProcessClose,
// rasman will never get a PPPMSG_Stopped. This is because pPcb will be
// deallocated and gone by the time we call ProcessClose. Note that we
// process a LineDown immediately and do not put it only at the end of
// the worker queue.
//
// DDM is not affected because of PPPDDMMSG_PortCleanedUp above.
//
//
// If should be OK to remove PCBFLAG_STOPPED_MSG_SENT. Most probably rasman
// can gracefully handle 2 PPPMSG_Stopped's. However, we don't want to take
// chances this close to shipping.
// moved to post line down
/*
if ( !(pPcb->fFlags & PCBFLAG_IS_SERVER )
&& !(pPcb->fFlags & PCBFLAG_STOPPED_MSG_SENT) )
{
DWORD dwError = 0;
NotifyCaller( pPcb, PPPMSG_Stopped, &dwError );
}
if ( pPcb->fFlags & PCBFLAG_PORT_IN_LISTENING_STATE )
{
//
// This flag is set in FListenForCall in bap.c
//
NotifyCallerOfFailure( pPcb, NO_ERROR );
}
LOCAL_FREE( pPcb );
*/
//if there are accounting attributes,
if ( pPcb->pAccountingAttributes != NULL )
{
//do not call the post line down
//in ProcessLineDown but let the accounting thread send a message back to indicate that it is done
*pfFinalStage = FALSE;
}
}
//**
//
// Call: ProcessLineDown
//
// Returns: None.
//
// Description: Handles a line down event. Will remove and deallocate all
// resources associated with the port control block.
//
VOID
ProcessLineDown(
IN PCB_WORK_ITEM * pWorkItem
)
{
BOOL fFinalStage = TRUE; //tells us if we should call ProcessPostLineDown
//right here or let accounting thread call it.
PCB * pPcb = GetPCBPointerFromhPort( pWorkItem->hPort );
ProcessLineDownWorker( pWorkItem, &fFinalStage );
if ( fFinalStage )
{
PostLineDownWorker(pPcb);
}
}
//**
//
// Call: ProcessClose
//
// Returns: None
//
// Description: Will process an admin close event. Basically close the PPP
// connection.
//
VOID
ProcessClose(
IN PCB_WORK_ITEM * pWorkItem
)
{
DWORD dwIndex;
PCB * pPcb = GetPCBPointerFromhPort( pWorkItem->hPort );
if ( pPcb == (PCB*)NULL )
{
return;
}
if ( (!( pPcb->fFlags & PCBFLAG_IS_BUNDLED )) ||
( ( pPcb->fFlags & PCBFLAG_IS_BUNDLED ) &&
( pPcb->pBcb->dwLinkCount == 1 ) ) )
{
for (dwIndex = LCP_INDEX+1;
dwIndex < PppConfigInfo.NumberOfCPs;
dwIndex++)
{
CPCB * pCpCb = GetPointerToCPCB( pPcb, dwIndex );
if ( ( NULL != pCpCb ) &&
( pCpCb->fConfigurable == TRUE ) &&
( pCpCb->pWorkBuf != NULL ) &&
( CpTable[dwIndex].CpInfo.RasCpPreDisconnectCleanup != NULL ) )
{
(CpTable[dwIndex].CpInfo.RasCpPreDisconnectCleanup)(
pCpCb->pWorkBuf );
}
}
}
if ( pPcb->LcpCb.dwError == NO_ERROR )
{
pPcb->LcpCb.dwError = pWorkItem->PppMsg.PppStop.dwStopReason;
}
FsmClose( pPcb, LCP_INDEX );
}
//**
//
// Call: ProcessReceive
//
// Returns: None
//
// Description: Will handle a PPP packet that was received.
//
VOID
ProcessReceive(
IN PCB_WORK_ITEM * pWorkItem
)
{
PCB * pPcb = GetPCBPointerFromhPort( pWorkItem->hPort );
if ( pPcb == (PCB*)NULL )
return;
ReceiveViaParser( pPcb, pWorkItem->pPacketBuf, pWorkItem->PacketLen );
LOCAL_FREE( pWorkItem->pPacketBuf );
}
//**
//
// Call: ProcessThresholdEvent
//
// Returns: None
//
// Description: Will handle a BAP threshold event (Add-Link or Drop-Link)
//
VOID
ProcessThresholdEvent(
IN PCB_WORK_ITEM * pWorkItem
)
{
BCB * pBcb = GetBCBPointerFromhConnection( pWorkItem->hConnection );
if ( pBcb == NULL )
{
BapTrace( "HCONN %d has no port", pWorkItem->hConnection );
return;
}
if ( pWorkItem->PppMsg.BapEvent.fAdd )
{
BapEventAddLink( pBcb );
}
else
{
BapEventDropLink( pBcb );
}
BapSetPolicy( pBcb );
}
//**
//
// Call: ProcessCallResult
//
// Returns: None
//
// Description: Will handle the result of a BAP call attempt (Success or Failure)
//
VOID
ProcessCallResult(
IN PCB_WORK_ITEM * pWorkItem
)
{
PCB * pPcb;
BCB * pBcb = GetBCBPointerFromhConnection(pWorkItem->hConnection);
DWORD dwErr;
if ( pBcb == NULL )
{
BapTrace( "HCONN 0x%x has no port", pWorkItem->hConnection );
dwErr = RasHangUp( pWorkItem->PppMsg.BapCallResult.hRasConn );
if (0 != dwErr)
{
BapTrace("RasHangup failed and returned %d", dwErr);
}
return;
}
PPP_ASSERT( BAP_STATE_CALLING == pBcb->BapCb.BapState );
BapEventCallResult( pBcb, &(pWorkItem->PppMsg.BapCallResult) );
}
//**
//
// Call: ProcessRasPortListenEvent
//
// Returns: None
//
// Description: Will handle a RasPortListen event (when the client is trying to
// accept a call).
//
VOID
ProcessRasPortListenEvent(
IN PCB_WORK_ITEM * pWorkItem
)
{
RASMAN_INFO RasmanInfo;
RASMAN_PPPFEATURES RasmanPppFeatures;
DWORD dwErr;
PCB * pPcb = NULL;
BCB * pBcb = NULL;
PCB * pPcbSibling;
CHAR szPassword[PWLEN+1];
ZeroMemory( &RasmanPppFeatures, sizeof(RasmanPppFeatures) );
RasmanPppFeatures.ACCM = 0xFFFFFFFF;
pPcb = GetPCBPointerFromhPort( pWorkItem->hPort );
if ( NULL == pPcb )
{
BapTrace( "Couldn't get the PCB for hPort %d", pWorkItem->hPort );
dwErr = ERROR_PORT_NOT_FOUND;
goto LDone;
}
//
// We can't just use pPcb->pBcb because TryToBundleWithAnotherLink(), etc
// have not yet been called. pPcb->hConnection was set in FListenForCall()
//
pBcb = GetBCBPointerFromhConnection( pPcb->hConnection );
if ( NULL == pBcb )
{
BapTrace( "Couldn't get the BCB for HCONN 0x%x", pPcb->hConnection );
dwErr = ERROR_BUNDLE_NOT_FOUND;
goto LDone;
}
BapTrace( "ProcessRasPortListenEvent on HCONN 0x%x", pBcb->hConnection );
dwErr = RasGetInfo(NULL, pPcb->hPort, &RasmanInfo );
if ( NO_ERROR == dwErr )
{
dwErr = RasmanInfo.RI_LastError;
}
if ( NO_ERROR != dwErr )
{
DWORD dwErrT;
BapTrace( "RasGetInfo on hPort %d returned error %d%s",
pPcb->hPort, dwErr,
dwErr == ERROR_REQUEST_TIMEOUT ? " (ERROR_REQUEST_TIMEOUT)" : "" );
if(0 == (RasmanInfo.RI_CurrentUsage & CALL_IN))
{
//
// Disconnect the port that was listening.
//
dwErrT = RasPortDisconnect(pPcb->hPort, INVALID_HANDLE_VALUE);
BapTrace("RasPortDisconnect returned %d", dwErrT);
}
//
// Close the port.
//
dwErrT = RasPortClose(pPcb->hPort);
BapTrace("RasPortDisconnect returned %d", dwErrT);
goto LDone;
}
if ( LISTENCOMPLETED == RasmanInfo.RI_ConnState )
{
DWORD cbPassword;
PBYTE pbPassword = NULL;
dwErr = RasPortConnectComplete( pPcb->hPort );
if ( NO_ERROR != dwErr )
{
BapTrace( "RasPortConnectComplete on hPort %d returned error %d",
pPcb->hPort, dwErr );
goto LDone;
}
dwErr = RasPortSetFraming( pPcb->hPort, PPP, &RasmanPppFeatures,
&RasmanPppFeatures );
if ( NO_ERROR != dwErr )
{
BapTrace( "RasPortSetFraming on hPort %d returned error %d",
pPcb->hPort, dwErr );
goto LDone;
}
pPcbSibling = GetPCBPointerFromBCB( pBcb );
if ( NULL == pPcbSibling )
{
BapTrace( "Couldn't get a PCB for HCONN 0x%x", pPcb->hConnection );
dwErr = !NO_ERROR;
goto LDone;
}
// DecodePw( pPcbSibling->pBcb->chSeed, pPcbSibling->pBcb->szPassword );
dwErr = DecodePassword(&pPcbSibling->pBcb->DBPassword,
&cbPassword, &pbPassword);
if(NO_ERROR != dwErr)
{
BapTrace("DecodePassword failed. 0x%x", dwErr);
goto LDone;
}
*szPassword = '\0';
CopyMemory(szPassword, pbPassword, cbPassword);
RtlSecureZeroMemory(pbPassword, cbPassword);
LocalFree(pbPassword);
// EncodePw( pPcbSibling->pBcb->chSeed, pPcbSibling->pBcb->szPassword );
if ( NULL != pPcbSibling->pBcb->pCustomAuthConnData )
{
dwErr = RasSetRasdialInfo(
pPcb->hPort,
pPcbSibling->pBcb->szPhonebookPath,
pPcbSibling->pBcb->szEntryName,
pPcbSibling->pBcb->BapCb.szServerPhoneNumber,
pPcbSibling->pBcb->pCustomAuthConnData->cbCustomAuthData,
pPcbSibling->pBcb->pCustomAuthConnData->abCustomAuthData );
if ( NO_ERROR != dwErr )
{
BapTrace( "RasSetRasDialInfo failed. dwErr = %d", dwErr );
goto LDone;
}
}
if ( NULL != pPcbSibling->pBcb->pCustomAuthUserData )
{
RASEAPINFO RasEapInfo;
RasEapInfo.dwSizeofEapInfo =
pPcbSibling->pBcb->pCustomAuthUserData->cbCustomAuthData;
RasEapInfo.pbEapInfo =
pPcbSibling->pBcb->pCustomAuthUserData->abCustomAuthData;
dwErr = RasSetEapLogonInfo(
pPcb->hPort,
FALSE /* fLogon */,
&RasEapInfo );
if ( NO_ERROR != dwErr )
{
BapTrace( "RasSetEapLogonInfo failed. dwErr = %d", dwErr );
goto LDone;
}
}
// This function returns before any LCP packet is exchanged.
dwErr = RasPppStart(
pPcb->hPort,
pPcb->szPortName,
pPcbSibling->pBcb->szLocalUserName,
szPassword,
pPcbSibling->pBcb->szLocalDomain,
&(pPcbSibling->Luid),
&(pPcbSibling->ConfigInfo),
&(pBcb->InterfaceInfo),
pBcb->InterfaceInfo.szzParameters,
FALSE /* fThisIsACallback */,
INVALID_HANDLE_VALUE,
pPcbSibling->dwAutoDisconnectTime,
FALSE /* fRedialOnLinkFailure */,
&(pPcbSibling->pBcb->BapParams),
TRUE /* fNonInteractive */,
pPcbSibling->dwEapTypeToBeUsed,
(pPcbSibling->fFlags & PCBFLAG_DISABLE_NETBT) ?
PPPFLAGS_DisableNetbt : 0
);
if ( NO_ERROR != dwErr )
{
BapTrace( "RasPppStart failed. dwErr = %d", dwErr );
goto LDone;
}
BapTrace( "RasPppStart called successfully for hPort %d on HCONN 0x%x",
pPcb->hPort, pBcb->hConnection );
{
CHAR* apsz[3];
apsz[0] = pPcbSibling->pBcb->szEntryName;
apsz[1] = pPcbSibling->pBcb->szLocalUserName;
apsz[2] = pPcb->szPortName;
PppLogInformation(ROUTERLOG_BAP_SERVER_CONNECTED, 3, apsz);
}
}
LDone:
RtlSecureZeroMemory(szPassword, PWLEN + 1);
if (NULL != pBcb)
{
pBcb->fFlags &= ~BCBFLAG_LISTENING;
pBcb->BapCb.BapState = BAP_STATE_INITIAL;
BapTrace("BAP state change to %s on HCONN 0x%x",
SzBapStateName[BAP_STATE_INITIAL], pBcb->hConnection);
}
if (NO_ERROR != dwErr && NULL != pPcb)
{
NotifyCallerOfFailure( pPcb, NO_ERROR );
RemovePcbFromTable( pPcb );
LOCAL_FREE( pPcb );
}
}
//**
//
// Call: ProcessTimeout
//
// Returns: None
//
// Description: Will process a timeout event.
//
VOID
ProcessTimeout(
IN PCB_WORK_ITEM * pWorkItem
)
{
DWORD dwRetCode;
DWORD dwIndex;
CPCB * pCpCb;
BCB * pBcb;
PCB * pPcb;
if ( pWorkItem->Protocol == PPP_BAP_PROTOCOL )
{
//
// The hPort in pWorkItem is actually an hConnection
//
pBcb = GetBCBPointerFromhConnection( pWorkItem->hPort );
if (pBcb != NULL)
{
BapEventTimeout( pBcb, pWorkItem->Id );
}
return;
}
pPcb = GetPCBPointerFromhPort( pWorkItem->hPort );
if ( ( pPcb == (PCB*)NULL )
|| ( pWorkItem->dwPortId != pPcb->dwPortId ) )
{
return;
}
switch( pWorkItem->TimerEventType )
{
case TIMER_EVENT_TIMEOUT:
FsmTimeout( pPcb,
GetCpIndexFromProtocol( pWorkItem->Protocol ),
pWorkItem->Id,
pWorkItem->fAuthenticator );
break;
case TIMER_EVENT_AUTODISCONNECT:
//
// Check to see if this timeout workitem is for AutoDisconnect.
//
CheckCpsForInactivity( pPcb, TIMER_EVENT_AUTODISCONNECT );
break;
case TIMER_EVENT_HANGUP:
//
// Hangup the line
//
FsmThisLayerFinished( pPcb, LCP_INDEX, FALSE );
break;
case TIMER_EVENT_NEGOTIATETIME:
//
// Notify caller that callback has timed out. We don't do anything for
// the client since it may be in interactive mode and may take much
// longer, besides, the user can allways cancel out.
//
if ( pPcb->fFlags & PCBFLAG_IS_SERVER )
{
if ( pPcb->PppPhase != PPP_NCP )
{
pPcb->LcpCb.dwError = ERROR_PPP_TIMEOUT;
NotifyCallerOfFailure( pPcb, pPcb->LcpCb.dwError );
break;
}
//
// Check to see if all CPs are done or only IPXCP is remaining
//
for ( dwIndex = LCP_INDEX+1;
dwIndex < PppConfigInfo.NumberOfCPs;
dwIndex++)
{
pCpCb = GetPointerToCPCB( pPcb, dwIndex );
if ( pCpCb->fConfigurable )
{
if ( pCpCb->NcpPhase == NCP_CONFIGURING )
{
if ( CpTable[dwIndex].CpInfo.Protocol ==
PPP_IPXCP_PROTOCOL )
{
//
// If we are only waiting for IPXWAN to complete
//
if ( pCpCb->State == FSM_OPENED )
{
continue;
}
}
pPcb->LcpCb.dwError = ERROR_PPP_TIMEOUT;
NotifyCallerOfFailure( pPcb, pPcb->LcpCb.dwError );
return;
}
}
}
dwIndex = GetCpIndexFromProtocol( PPP_IPXCP_PROTOCOL );
if ( dwIndex == (DWORD)-1 )
{
//
// No IPXCP installed in system
//
break;
}
pCpCb = GetPointerToCPCB( pPcb, dwIndex );
//
// We are waiting for IPXWAN so simply complete it with failure
//
if ( ( pCpCb->State == FSM_OPENED ) &&
( pCpCb->NcpPhase == NCP_CONFIGURING ) )
{
PppLog( 2,
"Closing down IPXCP since completion routine not called");
pCpCb = GetPointerToCPCB( pPcb, dwIndex );
pCpCb->dwError = ERROR_PPP_NOT_CONVERGING;
NotifyCallerOfFailure( pPcb, pCpCb->dwError );
}
}
else
{
if ( ( pPcb->pBcb->InterfaceInfo.IfType ==
ROUTER_IF_TYPE_FULL_ROUTER )
|| ( pPcb->fFlags & PCBFLAG_NON_INTERACTIVE ) )
{
//
// If we are a router dialing out, then we are in
// non-interactive mode and hence this timeout should bring
// down the link
//
pPcb->LcpCb.dwError = ERROR_PPP_TIMEOUT;
NotifyCallerOfFailure( pPcb, pPcb->LcpCb.dwError );
}
}
break;
case TIMER_EVENT_SESSION_TIMEOUT:
if ( pWorkItem->dwPortId == pPcb->dwPortId )
{
pPcb->LcpCb.dwError = ERROR_PPP_SESSION_TIMEOUT;
if(pPcb->pBcb->fFlags & BCBFLAG_QUARANTINE_TIMEOUT)
{
pPcb->fFlags |= PCBFLAG_QUARANTINE_TIMEOUT;
}
NotifyCallerOfFailure( pPcb, pPcb->LcpCb.dwError );
}
break;
case TIMER_EVENT_FAV_PEER_TIMEOUT:
//
// Drop the line if it isn't the last one in the bundle
//
if ( pPcb->pBcb->dwLinkCount > 1 &&
pWorkItem->dwPortId == pPcb->dwPortId)
{
//
// We compare dwPortId just to make sure that this is not a new
// pPcb with the same hPort. dwPortId is never recycled, but hPort
// is.
//
CHAR* psz[3];
if (!(pPcb->fFlags & PCBFLAG_IS_SERVER))
{
psz[0] = pPcb->pBcb->szEntryName;
psz[1] = pPcb->pBcb->szLocalUserName;
psz[2] = pPcb->szPortName;
PppLogInformation(ROUTERLOG_BAP_DISCONNECTED, 3, psz);
}
BapTrace( "Forcibly disconnecting hPort %d: Favored peer failed "
"to do so",
pPcb->hPort);
pPcb->LcpCb.dwError = ERROR_BAP_DISCONNECTED;
FsmClose( pPcb, LCP_INDEX );
}
break;
case TIMER_EVENT_INTERIM_ACCOUNTING:
{
RAS_AUTH_ATTRIBUTE * pAttributes = NULL;
RAS_AUTH_ATTRIBUTE * pAttribute = NULL;
MakeStopOrInterimAccountingCall( pPcb, TRUE );
if ( pPcb->pAuthProtocolAttributes != NULL )
{
pAttributes = pPcb->pAuthProtocolAttributes;
}
else if ( pPcb->pAuthenticatorAttributes != NULL )
{
pAttributes = pPcb->pAuthenticatorAttributes;
}
pAttribute = RasAuthAttributeGet(raatAcctInterimInterval,
pAttributes);
if ( pAttribute != NULL )
{
DWORD dwInterimInterval = PtrToUlong(pAttribute->Value);
if ( dwInterimInterval < 60 )
{
dwInterimInterval = 60;
}
InsertInTimerQ(
pPcb->dwPortId,
pPcb->hPort,
0,
0,
FALSE,
TIMER_EVENT_INTERIM_ACCOUNTING,
dwInterimInterval );
}
}
break;
case TIMER_EVENT_LCP_ECHO:
{
//
// Check to see if this timeout workitem is for AutoDisconnect.
//
CheckCpsForInactivity( pPcb, TIMER_EVENT_LCP_ECHO );
}
break;
default:
break;
}
}
//**
//
// Call: ProcessRetryPassword
//
// Returns: None
//
// Description:
//
VOID
ProcessRetryPassword(
IN PCB_WORK_ITEM * pWorkItem
)
{
PPPAP_INPUT PppApInput;
PCB * pPcb = GetPCBPointerFromhPort( pWorkItem->hPort );
LCPCB * pLcpCb;
DWORD cbPassword;
PBYTE pbPassword = NULL;
DWORD dwRetCode = NO_ERROR;
if ( pPcb == (PCB*)NULL )
{
return;
}
if ( pPcb->PppPhase != PPP_AP )
{
return;
}
RtlSecureZeroMemory( pPcb->pBcb->szPassword, sizeof( pPcb->pBcb->szPassword ) );
strcpy( pPcb->pBcb->szLocalUserName, pWorkItem->PppMsg.Retry.szUserName );
// DecodePw( pWorkItem->PppMsg.Retry.chSeed, pWorkItem->PppMsg.Retry.szPassword );
dwRetCode = DecodePassword(&pWorkItem->PppMsg.Retry.DBPassword,
&cbPassword, &pbPassword);
if(NO_ERROR != dwRetCode)
{
goto done;
}
// strcpy( pPcb->pBcb->szPassword, pWorkItem->PppMsg.Retry.szPassword );
FreePassword(&pPcb->pBcb->DBPassword);
CopyMemory(&pPcb->pBcb->DBPassword,
&pWorkItem->PppMsg.Retry.DBPassword,
sizeof(DATA_BLOB));
// EncodePw( pWorkItem->PppMsg.Retry.chSeed, pWorkItem->PppMsg.Retry.szPassword );
strcpy( pPcb->pBcb->szLocalDomain, pWorkItem->PppMsg.Retry.szDomain );
PppApInput.pszUserName = pPcb->pBcb->szLocalUserName;
PppApInput.pszPassword = pbPassword;
PppApInput.pszDomain = pPcb->pBcb->szLocalDomain;
//
// Under the current scheme this should always be "" at this point but
// handle it like it a regular password for robustness.
//
// DecodePw( pPcb->pBcb->chSeed, pPcb->pBcb->szOldPassword );
PppApInput.pszOldPassword = pPcb->pBcb->szOldPassword;
pLcpCb = (LCPCB *)(pPcb->LcpCb.pWorkBuf);
ApWork( pPcb,
GetCpIndexFromProtocol( pLcpCb->Remote.Work.AP ),
NULL,
&PppApInput,
FALSE );
done:
RtlSecureZeroMemory(pbPassword, cbPassword);
LocalFree(pbPassword);
//
// Encrypt the password
//
// EncodePw( pPcb->pBcb->chSeed, pPcb->pBcb->szPassword );
// EncodePw( pPcb->pBcb->chSeed, pPcb->pBcb->szOldPassword );
}
//**
//
// Call: ProcessChangePassword
//
// Returns: None
//
// Description:
//
VOID
ProcessChangePassword(
IN PCB_WORK_ITEM * pWorkItem
)
{
PPPAP_INPUT PppApInput;
PCB * pPcb = GetPCBPointerFromhPort( pWorkItem->hPort );
CPCB * pCpCb;
LCPCB * pLcpCb;
DWORD cbOldPassword, cbNewPassword;
PBYTE pbOldPassword = NULL, pbNewPassword = NULL;
DWORD dwRetCode = NO_ERROR;
if ( pPcb == (PCB*)NULL )
{
return;
}
if ( pPcb->PppPhase != PPP_AP )
{
return;
}
ZeroMemory( pPcb->pBcb->szLocalUserName,
sizeof( pPcb->pBcb->szLocalUserName ) );
strcpy(pPcb->pBcb->szLocalUserName, pWorkItem->PppMsg.ChangePw.szUserName);
// DecodePw( pWorkItem->PppMsg.ChangePw.chSeed, pWorkItem->PppMsg.ChangePw.szNewPassword );
// RtlSecureZeroMemory( pPcb->pBcb->szPassword, sizeof( pPcb->pBcb->szPassword ) );
dwRetCode = DecodePassword(&pWorkItem->PppMsg.ChangePw.DBPassword,
&cbNewPassword, &pbNewPassword);
if(dwRetCode != NO_ERROR)
{
goto done;
}
dwRetCode = DecodePassword(&pWorkItem->PppMsg.ChangePw.DBOldPassword,
&cbOldPassword, &pbOldPassword);
if(dwRetCode != NO_ERROR)
{
goto done;
}
FreePassword(&pPcb->pBcb->DBPassword);
CopyMemory(&pPcb->pBcb->DBPassword,
&pWorkItem->PppMsg.ChangePw.DBPassword,
sizeof(DATA_BLOB));
ZeroMemory(&pWorkItem->PppMsg.ChangePw.DBPassword,
sizeof(DATA_BLOB));
FreePassword(&pPcb->pBcb->DBOldPassword);
CopyMemory(&pPcb->pBcb->DBOldPassword,
&pWorkItem->PppMsg.ChangePw.DBOldPassword,
sizeof(DATA_BLOB));
ZeroMemory(&pWorkItem->PppMsg.ChangePw.DBOldPassword,
sizeof(DATA_BLOB));
// strcpy(pPcb->pBcb->szOldPassword, pWorkItem->PppMsg.ChangePw.szOldPassword);
// EncodePw( pWorkItem->PppMsg.ChangePw.chSeed, pWorkItem->PppMsg.ChangePw.szOldPassword );
PppApInput.pszUserName = pPcb->pBcb->szLocalUserName;
PppApInput.pszPassword = pbNewPassword;
PppApInput.pszDomain = pPcb->pBcb->szLocalDomain;
PppApInput.pszOldPassword = pbOldPassword;
pLcpCb = (LCPCB *)(pPcb->LcpCb.pWorkBuf);
ApWork( pPcb,
GetCpIndexFromProtocol( pLcpCb->Remote.Work.AP ),
NULL,
&PppApInput,
FALSE );
done:
RtlSecureZeroMemory(pbNewPassword, cbNewPassword);
RtlSecureZeroMemory(pbOldPassword, cbOldPassword);
LocalFree(pbNewPassword);
LocalFree(pbOldPassword);
//
// Encrypt the passwords
//
// EncodePw( pPcb->pBcb->chSeed, pPcb->pBcb->szPassword );
// EncodePw( pPcb->pBcb->chSeed, pPcb->pBcb->szOldPassword );
}
//**
//
// Call: ProcessGetCallbackNumberFromUser
//
// Returns: None
//
// Description: Will process the event of the user passing down the
// "Set by caller" number
//
VOID
ProcessGetCallbackNumberFromUser(
IN PCB_WORK_ITEM * pWorkItem
)
{
PPPCB_INPUT PppCbInput;
PCB * pPcb = GetPCBPointerFromhPort( pWorkItem->hPort );
if ( pPcb == (PCB*)NULL )
{
return;
}
if ( pPcb->PppPhase != PPP_NEGOTIATING_CALLBACK )
{
return;
}
ZeroMemory( &PppCbInput, sizeof( PppCbInput ) );
strcpy( pPcb->szCallbackNumber,
pWorkItem->PppMsg.Callback.szCallbackNumber );
PppCbInput.pszCallbackNumber = pPcb->szCallbackNumber;
CbWork( pPcb, GetCpIndexFromProtocol(PPP_CBCP_PROTOCOL),NULL,&PppCbInput);
}
//**
//
// Call: ProcessCallbackDone
//
// Returns: None
//
// Description: Will process the event of callback compeletion
// "Set by caller" number
VOID
ProcessCallbackDone(
IN PCB_WORK_ITEM * pWorkItem
)
{
ProcessLineUpWorker( pWorkItem, TRUE );
}
//**
//
// Call: ProcessStopPPP
//
// Returns: None
//
// Description: Will simply set the events whose handle is in hPipe
//
VOID
ProcessStopPPP(
IN PCB_WORK_ITEM * pWorkItem
)
{
PRAS_OVERLAPPED pOverlapped;
HINSTANCE hInstance;
PCB * pPcbWalker;
DWORD dwIndex;
PCB_WORK_ITEM WorkItem;
HANDLE hEvent;
//
// Insert line down events for all ports
//
for ( dwIndex = 0; dwIndex < PcbTable.NumPcbBuckets; dwIndex++ )
{
RTASSERT( NULL == PcbTable.PcbBuckets[dwIndex].pPorts );
}
hInstance = LoadLibrary("rasppp.dll");
if (hInstance == NULL)
{
return;
}
PppLog( 2, "All clients disconnected PPP-Stopped" );
hEvent = pWorkItem->hEvent;
//
// PPPCleanUp() needs to be called before PostQueued...(). Otherwise,
// Rasman may call StartPPP() and there will be a race condition.
// Specifically, between ReadRegistryInfo and PPPCleanUp, both of which
// access CpTable.
//
PPPCleanUp();
pOverlapped = malloc(sizeof(RAS_OVERLAPPED));
if (NULL == pOverlapped)
{
return;
}
pOverlapped->RO_EventType = OVEVT_RASMAN_FINAL_CLOSE;
if ( !PostQueuedCompletionStatus( hEvent, 0, 0, (LPOVERLAPPED) pOverlapped ) )
{
free( pOverlapped );
}
FreeLibraryAndExitThread( hInstance, NO_ERROR );
}
//**
//
// Call: ProcessInterfaceInfo
//
// Returns: None
//
// Description: Processes the information interface information received from
// DDM
//
VOID
ProcessInterfaceInfo(
IN PCB_WORK_ITEM * pWorkItem
)
{
DWORD dwRetCode;
DWORD dwIndex;
NCP_PHASE dwNcpState;
HPORT hPort;
PCB * pPcb = NULL;
CPCB * pCpCb;
dwRetCode = RasBundleGetPort(NULL, pWorkItem->hConnection, &hPort );
if ( dwRetCode != NO_ERROR )
{
return;
}
if ( ( pPcb = GetPCBPointerFromhPort( hPort ) ) == NULL )
{
return;
}
pCpCb = GetPointerToCPCB( pPcb, LCP_INDEX );
PPP_ASSERT( NULL != pCpCb );
if ( FSM_OPENED != pCpCb->State )
{
return;
}
pPcb->PppPhase = PPP_NCP;
pPcb->pBcb->InterfaceInfo = pWorkItem->PppMsg.InterfaceInfo;
if ( ROUTER_IF_TYPE_FULL_ROUTER == pPcb->pBcb->InterfaceInfo.IfType )
{
if ( NULL == pPcb->pBcb->szPhonebookPath )
{
dwRetCode = GetRouterPhoneBook( &(pPcb->pBcb->szPhonebookPath) );
if ( dwRetCode != NO_ERROR )
{
pPcb->LcpCb.dwError = dwRetCode;
NotifyCallerOfFailure( pPcb, pPcb->LcpCb.dwError );
return;
}
}
if ( NULL == pPcb->pBcb->szEntryName )
{
pPcb->pBcb->szEntryName =
LocalAlloc( LPTR, (lstrlen(pPcb->pBcb->szRemoteUserName)+1) *
sizeof(CHAR));
if ( NULL == pPcb->pBcb->szEntryName )
{
pPcb->LcpCb.dwError = GetLastError();
NotifyCallerOfFailure( pPcb, pPcb->LcpCb.dwError );
return;
}
lstrcpy( pPcb->pBcb->szEntryName, pPcb->pBcb->szRemoteUserName );
}
//
// Even if an error occurs, we don't have to free the alloc'd strings.
// They will be freed when pPcb is freed.
//
}
//
// If we are not bundled.
//
if ( !(pPcb->fFlags & PCBFLAG_IS_BUNDLED) )
{
dwRetCode = InitializeNCPs( pPcb, pPcb->ConfigInfo.dwConfigMask );
if ( dwRetCode != NO_ERROR )
{
pPcb->LcpCb.dwError = dwRetCode;
NotifyCallerOfFailure( pPcb, pPcb->LcpCb.dwError );
return;
}
//
// Start negotiating the NCPs
//
StartNegotiatingNCPs( pPcb );
return;
}
//
// If we are bundled.
// If negotiation has not started then start it, otherwise wait for it to
// finish.
//
dwNcpState = QueryBundleNCPState( pPcb );
switch ( dwNcpState )
{
case NCP_UP:
NotifyCallerOfBundledProjection( pPcb );
RemoveFromTimerQ( pPcb->dwPortId,
0,
0,
FALSE,
TIMER_EVENT_NEGOTIATETIME );
StartAutoDisconnectForPort( pPcb );
StartLCPEchoForPort ( pPcb );
break;
case NCP_CONFIGURING:
PppLog( 2, "Bundle NCPs not done for port %d, wait", pPcb->hPort );
break;
case NCP_DOWN:
pPcb->LcpCb.dwError = ERROR_PPP_NO_PROTOCOLS_CONFIGURED;
NotifyCallerOfFailure( pPcb, pPcb->LcpCb.dwError );
break;
case NCP_DEAD:
dwRetCode = InitializeNCPs( pPcb, pPcb->ConfigInfo.dwConfigMask );
if ( dwRetCode != NO_ERROR )
{
pPcb->LcpCb.dwError = dwRetCode;
NotifyCallerOfFailure( pPcb, pPcb->LcpCb.dwError );
return;
}
//
// Start NCPs for the bundle.
//
StartNegotiatingNCPs( pPcb );
break;
}
}
//**
//
// Call: ProcessAuthInfo
//
// Returns: None
//
// Description: Processes the information returned by the back-end
// authentication module
//
VOID
ProcessAuthInfo(
IN PCB_WORK_ITEM * pWorkItem
)
{
PCB * pPcb = GetPCBPointerFromhPort( pWorkItem->hPort );
LCPCB * pLcpCb = NULL;
DWORD CpIndex;
PPPAP_INPUT PppApInput;
DWORD dwRetCode;
//
// If we couldn't find the PCB because the port is disconnected
//
if ( pPcb == NULL )
{
if ( pWorkItem->PppMsg.AuthInfo.pOutAttributes != NULL )
{
PppConfigInfo.RasAuthProviderFreeAttributes(
pWorkItem->PppMsg.AuthInfo.pOutAttributes );
}
return;
}
pLcpCb = (LCPCB*)(pPcb->LcpCb.pWorkBuf);
//
// If this is a different instance of this port, ie port was disconnected
// and reconnected.
//
if ( pPcb->dwPortId != pWorkItem->dwPortId )
{
if ( pWorkItem->PppMsg.AuthInfo.pOutAttributes != NULL )
{
PppConfigInfo.RasAuthProviderFreeAttributes(
pWorkItem->PppMsg.AuthInfo.pOutAttributes );
}
return;
}
CpIndex = GetCpIndexFromProtocol( pWorkItem->Protocol );
//
// If we renegotiated a different authentication protocol
//
if ( CpIndex != GetCpIndexFromProtocol( pLcpCb->Local.Work.AP ) )
{
PppConfigInfo.RasAuthProviderFreeAttributes(
pWorkItem->PppMsg.AuthInfo.pOutAttributes );
return;
}
//
// If the id of this request doesn't match
//
if ( pWorkItem->PppMsg.AuthInfo.dwId != pPcb->dwOutstandingAuthRequestId )
{
if ( pWorkItem->PppMsg.AuthInfo.pOutAttributes != NULL )
{
PppConfigInfo.RasAuthProviderFreeAttributes(
pWorkItem->PppMsg.AuthInfo.pOutAttributes );
}
return;
}
if ( 0 == pLcpCb->Local.Work.AP )
{
do
{
dwRetCode = NO_ERROR;
if ( NO_ERROR != pWorkItem->PppMsg.AuthInfo.dwError )
{
dwRetCode = pWorkItem->PppMsg.AuthInfo.dwError;
break;
}
if ( NO_ERROR != pWorkItem->PppMsg.AuthInfo.dwResultCode )
{
dwRetCode = pWorkItem->PppMsg.AuthInfo.dwResultCode;
break;
}
pPcb->pAuthenticatorAttributes =
pWorkItem->PppMsg.AuthInfo.pOutAttributes;
//
// Set all the user connection parameters authorized by the
// back-end authenticator
//
dwRetCode = SetUserAuthorizedAttributes(
pPcb,
pPcb->pAuthenticatorAttributes,
TRUE,
NULL,
NULL );
if ( dwRetCode != NO_ERROR )
{
break;
}
FsmThisLayerUp( pPcb, CpIndex );
}
while ( FALSE );
if ( NO_ERROR != dwRetCode )
{
pPcb->LcpCb.dwError = dwRetCode;
NotifyCallerOfFailure( pPcb, dwRetCode );
if ( pWorkItem->PppMsg.AuthInfo.pOutAttributes != NULL )
{
PppConfigInfo.RasAuthProviderFreeAttributes(
pWorkItem->PppMsg.AuthInfo.pOutAttributes );
}
}
return;
}
//
// If this authenticator is not configurable
//
if ( !pPcb->AuthenticatorCb.fConfigurable )
{
if ( pWorkItem->PppMsg.AuthInfo.pOutAttributes != NULL )
{
PppConfigInfo.RasAuthProviderFreeAttributes(
pWorkItem->PppMsg.AuthInfo.pOutAttributes );
}
return;
}
//
// Free previously allocated attributes if any.
//
if ( pPcb->pAuthenticatorAttributes != NULL )
{
PppConfigInfo.RasAuthProviderFreeAttributes(
pPcb->pAuthenticatorAttributes );
pPcb->pAuthenticatorAttributes = NULL;
}
ZeroMemory( &PppApInput, sizeof( PppApInput ) );
PppApInput.dwAuthResultCode = pWorkItem->PppMsg.AuthInfo.dwResultCode;
PppApInput.dwAuthError = pWorkItem->PppMsg.AuthInfo.dwError;
PppApInput.fAuthenticationComplete = TRUE;
pPcb->pAuthenticatorAttributes =
pWorkItem->PppMsg.AuthInfo.pOutAttributes;
PppApInput.pAttributesFromAuthenticator =
pWorkItem->PppMsg.AuthInfo.pOutAttributes;
ApWork( pPcb, CpIndex, NULL, &PppApInput, TRUE );
}
//**
//
// Call: ProcessDhcpInform
//
// Returns: None
//
// Description: Processes the information returned by the call to
// DhcpRequestOptions
//
VOID
ProcessDhcpInform(
IN PCB_WORK_ITEM * pWorkItem
)
{
DWORD dwErr;
PCB* pPcb;
HPORT hPort;
DWORD IPCPIndex;
CPCB* pCpCb;
BOOL fFree = TRUE;
PppLog( 2, "ProcessDhcpInform" );
dwErr = RasBundleGetPort(NULL, pWorkItem->hConnection, &hPort );
if ( dwErr != NO_ERROR )
{
PppLog( 2, "RasBundleGetPort(%d) failed: %d",
pWorkItem->hConnection, dwErr );
goto LDone;
}
if ( ( pPcb = GetPCBPointerFromhPort( hPort ) ) == NULL )
{
PppLog( 2, "GetPCBPointerFromhPort(%d) failed", hPort );
goto LDone;
}
IPCPIndex = GetCpIndexFromProtocol( PPP_IPCP_PROTOCOL );
if ( IPCPIndex == (DWORD)-1 )
{
PppLog( 2, "GetCpIndexFromProtocol(IPCP) failed" );
goto LDone;
}
pCpCb = GetPointerToCPCB( pPcb, IPCPIndex );
if ( NULL == pCpCb )
{
PppLog( 2, "GetPointerToCPCB(IPCP) failed" );
goto LDone;
}
if ( PppConfigInfo.RasIpcpDhcpInform != NULL )
{
dwErr = PppConfigInfo.RasIpcpDhcpInform(
pCpCb->pWorkBuf,
&(pWorkItem->PppMsg.DhcpInform) );
if ( NO_ERROR == dwErr )
{
fFree = FALSE;
}
}
LDone:
LocalFree(pWorkItem->PppMsg.DhcpInform.wszDevice);
LocalFree(pWorkItem->PppMsg.DhcpInform.szDomainName);
if (fFree)
{
LocalFree(pWorkItem->PppMsg.DhcpInform.pdwDNSAddresses);
}
}
//**
//
// Call: ProcessIpAddressLeaseExpired
//
// Returns: None
//
// Description: Processes the expiry of the lease of an Ip address from a
// Dhcp server.
//
VOID
ProcessIpAddressLeaseExpired(
IN PCB_WORK_ITEM * pWorkItem
)
{
PppLog( 2, "ProcessIpAddressLeaseExpired" );
if ( PppConfigInfo.RasIphlpDhcpCallback != NULL )
{
PppConfigInfo.RasIphlpDhcpCallback(
pWorkItem->PppMsg.IpAddressLeaseExpired.nboIpAddr );
}
}
//**
//
// Call: ProcessEapUIData
//
// Returns: None
//
// Description:
//
VOID
ProcessEapUIData(
IN PCB_WORK_ITEM * pWorkItem
)
{
PPPAP_INPUT PppApInput;
PCB * pPcb = GetPCBPointerFromhPort( pWorkItem->hPort );
LCPCB * pLcpCb;
if ( pPcb == (PCB*)NULL )
{
return;
}
if ( pPcb->PppPhase != PPP_AP )
{
return;
}
pLcpCb = (LCPCB *)(pPcb->LcpCb.pWorkBuf);
ZeroMemory( &PppApInput, sizeof( PppApInput ) );
PppApInput.fEapUIDataReceived = TRUE;
PppApInput.EapUIData = pWorkItem->PppMsg.EapUIData;
ApWork( pPcb,
GetCpIndexFromProtocol( pLcpCb->Remote.Work.AP ),
NULL,
&PppApInput,
FALSE );
//
// EapUIData.pEapUIData is allocated by rasman and freed by engine.
// raseap.c must not free it.
//
LocalFree( pWorkItem->PppMsg.EapUIData.pEapUIData );
}
//**
//
// Call: ProcessChangeNotification
//
// Returns: NO_ERROR - Success
// Non-zero returns - Failure
//
// Description: Will be called whenever there is a change in configuration
// that has to be picked up
//
VOID
ProcessChangeNotification(
IN PCB_WORK_ITEM * pWorkItem
)
{
DWORD dwIndex;
DWORD dwRetCode;
DWORD cTotalNumProtocols;
PppLog( 2, "Processing change notification event" );
//
// Re-read all the ppp key values
//
ReadPPPKeyValues( PppConfigInfo.hKeyPpp );
LoadParserDll( PppConfigInfo.hKeyPpp );
//
// Walk thru the CP table and invoke the change notification method
// for each one.
//
cTotalNumProtocols = PppConfigInfo.NumberOfCPs + PppConfigInfo.NumberOfAPs;
for ( dwIndex = 0; dwIndex < cTotalNumProtocols; dwIndex++ )
{
if ( ( CpTable[dwIndex].fFlags & PPPCP_FLAG_AVAILABLE ) &&
( CpTable[dwIndex].CpInfo.RasCpChangeNotification != NULL ) )
{
dwRetCode = CpTable[dwIndex].CpInfo.RasCpChangeNotification();
if ( dwRetCode != NO_ERROR )
{
PppLog( 2,
"ChangeNotification for Protocol 0x%x failed, error=%d",
CpTable[dwIndex].CpInfo.Protocol, dwRetCode );
}
}
}
}
//**
//
// Call: ProcessProtocolEvent
//
// Returns: None
//
// Description: Will be called whenever a protocol is installed or uninstalled.
//
VOID
ProcessProtocolEvent(
IN PCB_WORK_ITEM * pWorkItem
)
{
DWORD dwIndex;
DWORD dwProtocol;
DWORD cTotalNumProtocols;
CHAR* szSubKey;
CHAR* SubStringArray[2];
DWORD dwError;
PppLog( 2, "Processing protocol event" );
//
// Ignore any message other than one saying that a protocol was installed.
//
if ( pWorkItem->PppMsg.ProtocolEvent.ulFlags != RASMAN_PROTOCOL_ADDED )
{
if ( ( pWorkItem->PppMsg.ProtocolEvent.ulFlags ==
RASMAN_PROTOCOL_REMOVED )
&& ( pWorkItem->PppMsg.ProtocolEvent.usProtocolType == IP ) )
{
//
// NT5 Bug 398226. When PSched is installed/uninstalled, IP is
// unbound from wanarp so that PSched can be bound/unbound between
// IP and wanarp. The server adapter needs to be mapped again.
//
RasSrvrAdapterUnmapped();
}
return;
}
switch ( pWorkItem->PppMsg.ProtocolEvent.usProtocolType )
{
case IP:
dwProtocol = PPP_IPCP_PROTOCOL;
PppLog( 2, "Adding IP" );
break;
case IPX:
dwProtocol = PPP_IPXCP_PROTOCOL;
PppLog( 2, "Adding IPX" );
break;
case ASYBEUI:
dwProtocol = PPP_NBFCP_PROTOCOL;
PppLog( 2, "Adding ASYBEUI" );
break;
case APPLETALK:
dwProtocol = PPP_ATCP_PROTOCOL;
PppLog( 2, "Adding APPLETALK" );
break;
default:
return;
}
cTotalNumProtocols = PppConfigInfo.NumberOfCPs + PppConfigInfo.NumberOfAPs;
for ( dwIndex = 0; dwIndex < cTotalNumProtocols; dwIndex++ )
{
if ( dwProtocol == CpTable[dwIndex].CpInfo.Protocol )
{
if ( !( CpTable[dwIndex].fFlags & PPPCP_FLAG_INIT_CALLED )
&& CpTable[dwIndex].CpInfo.RasCpInit )
{
PppLog( 1, "RasCpInit(%x, TRUE)", dwProtocol );
dwError = CpTable[dwIndex].CpInfo.RasCpInit(
TRUE /* fInitialize */ );
CpTable[dwIndex].fFlags |= PPPCP_FLAG_INIT_CALLED;
if ( NO_ERROR != dwError )
{
SubStringArray[0] = CpTable[dwIndex].CpInfo.SzProtocolName;
SubStringArray[1] = "(unknown)";
PppLogErrorString(
ROUTERLOG_PPPCP_INIT_ERROR,
2,
SubStringArray,
dwError,
2 );
PppLog(
1,
"RasCpInit(TRUE) for protocol 0x%x returned error %d",
dwProtocol, dwError );
}
else
{
CpTable[dwIndex].fFlags |= PPPCP_FLAG_AVAILABLE;
}
}
return;
}
}
}
VOID
ProcessRemoveQuarantine(
IN PCB_WORK_ITEM *pWorkItem
)
{
BCB *pBcb = GetBCBPointerFromhConnection( pWorkItem->hConnection );
DWORD dwForIndex;
PCB *pPcb;
//
// If we had added quarantine session timeouts for ports on this
// bundle, remove the quarantine session timeout and add the
// regular session timeout
//
if( (NULL != pBcb)
&& (pBcb->fFlags & BCBFLAG_QUARANTINE_TIMEOUT))
{
for (dwForIndex = 0;
dwForIndex < pBcb->dwPpcbArraySize;
dwForIndex++)
{
pPcb = pBcb->ppPcb[dwForIndex];
if ( NULL == pPcb )
{
continue;
}
//
// Remove any previous session-disconnect time item from the
// queue if there was one.
//
PppLog(2,
"ProcessRemoveQuarantine: removing quarantine-session-timer");
RemoveFromTimerQ( pPcb->dwPortId,
0,
0,
FALSE,
TIMER_EVENT_SESSION_TIMEOUT );
if(pPcb->dwSessionTimeout > 0)
{
PppLog(2,
"ProcessRemoveQuarantine: adding session timeout %d",
pPcb->dwSessionTimeout);
InsertInTimerQ( pPcb->dwPortId,
pPcb->hPort,
0,
0,
FALSE,
TIMER_EVENT_SESSION_TIMEOUT,
pPcb->dwSessionTimeout );
}
}
pBcb->fFlags &= ~BCBFLAG_QUARANTINE_TIMEOUT;
}
return;
}
VOID
ProcessResumeFromHibernate(
IN PCB_WORK_ITEM *pWorkItem
)
{
PppConfigInfo.fFlags |= PPPCONFIG_FLAG_RESUME;
}