/********************************************************************/ /** 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 #include #include // needed for winbase.h #include // Win32 base API's #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define INCL_RASAUTHATTRIBUTES #define INCL_PWUTIL #include //** // // 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;dwIndexfBeginCalled == 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; }