|
|
/********************************************************************/ /** 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; }
|