|
|
/********************************************************************/ /** Copyright(c) 1989 Microsoft Corporation. **/ /********************************************************************/
//***
//
// Filename: util.c
//
// Description: Contains utility routines used by the PPP engine.
//
// History:
// Oct 31,1993. NarenG Created original version.
//
#define UNICODE // This file is in UNICODE
#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 <ctype.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <rpc.h>
#include <winsock2.h>
#include <rtinfo.h>
#include <iprtrmib.h>
#include <ipinfoid.h>
#include <lmcons.h>
#include <lmwksta.h>
#include <lmapibuf.h>
#include <lmsname.h>
#include <rasman.h>
#include <rtutils.h>
#include <mprapip.h>
#include <mprlog.h>
#include <raserror.h>
#include <mprerror.h>
#include <rasppp.h>
#include <pppcp.h>
#include <ppp.h>
#include <smevents.h>
#include <smaction.h>
#include <timer.h>
#include <util.h>
#include <worker.h>
#include <bap.h>
#include <dsrole.h>
#include <ntlsapi.h>
#define INCL_RASAUTHATTRIBUTES
#define INCL_PWUTIL
#include <ppputil.h>
#define PASSWORDMAGIC 0xA5
#define CLASSA_ADDR(a) (( (*((UCHAR *)&(a))) & 0x80) == 0)
#define CLASSB_ADDR(a) (( (*((UCHAR *)&(a))) & 0xc0) == 0x80)
#define CLASSC_ADDR(a) (( (*((UCHAR *)&(a))) & 0xe0) == 0xc0)
#define CLASSE_ADDR(a) ((( (*((UCHAR *)&(a))) & 0xf0) == 0xf0) && \
((a) != 0xffffffff))
#define CLASSA_MASK 0x000000ff
#define CLASSB_MASK 0x0000ffff
#define CLASSC_MASK 0x00ffffff
#define CLASSD_MASK 0x000000e0
#define CLASSE_MASK 0xffffffff
#define GetClassMask(a)\
(CLASSA_ADDR((a)) ? CLASSA_MASK : \ (CLASSB_ADDR((a)) ? CLASSB_MASK : \ (CLASSC_ADDR((a)) ? CLASSC_MASK : CLASSE_MASK)))
VOID ReverseString( CHAR* psz );
extern PPP_AUTH_ACCT_PROVIDER g_AcctProv;
//**
//
// Call: InitRestartCounters
//
// Returns: none.
//
// Description: Will initialize all the counters for the Control Protocol
// to their initial values.
//
VOID InitRestartCounters( IN PCB * pPcb, IN CPCB * pCpCb ) { pCpCb->ConfigRetryCount = PppConfigInfo.MaxConfigure; pCpCb->TermRetryCount = PppConfigInfo.MaxTerminate; }
//**
//
// Call: GetPCBPointerFromhPort
//
// Returns: PCB * - Success
// NULL - Failure
//
// Description: Give an HPORT, this function will return a pointer to the
// port control block for it.
//
PCB * GetPCBPointerFromhPort( IN HPORT hPort ) { PCB * pPcbWalker = NULL; DWORD dwIndex = HashPortToBucket( hPort );
for ( pPcbWalker = PcbTable.PcbBuckets[dwIndex].pPorts; pPcbWalker != (PCB *)NULL; pPcbWalker = pPcbWalker->pNext ) { if ( pPcbWalker->hPort == hPort ) return( pPcbWalker ); }
return( (PCB *)NULL );
}
//**
//
// Call: GetBCBPointerFromhConnection
//
// Returns: BCB * - Success
// NULL - Failure
//
// Description: Given an HCONN, this function will return a pointer to the
// bundle control block for it.
//
BCB * GetBCBPointerFromhConnection( IN HCONN hConnection ) { BCB * pBcbWalker = NULL; DWORD dwIndex = HashPortToBucket( hConnection );
for ( pBcbWalker = PcbTable.BcbBuckets[dwIndex].pBundles; pBcbWalker != (BCB *)NULL; pBcbWalker = pBcbWalker->pNext ) { if ( pBcbWalker->hConnection == hConnection ) return( pBcbWalker ); }
return( (BCB *)NULL ); }
//**
//
// Call: NumLinksInBundle
//
// Returns: The number of links whose LCP is in the Opened state in the bundle
// represented by pBcb
//
DWORD NumLinksInBundle( IN BCB * pBcb ) { DWORD dwForIndex; PCB * pPcb; CPCB * pCpCb; DWORD dwNumLinks = 0;
PPP_ASSERT( NULL != pBcb );
for (dwForIndex = 0; dwForIndex < pBcb->dwPpcbArraySize; dwForIndex++) { pPcb = pBcb->ppPcb[dwForIndex];
if ( NULL == pPcb ) { continue; }
pCpCb = GetPointerToCPCB( pPcb, LCP_INDEX ); PPP_ASSERT( NULL != pCpCb );
if ( FSM_OPENED == pCpCb->State ) { dwNumLinks += 1; } }
return( dwNumLinks ); }
//**
//
// Call: GetPCBPointerFromBCB
//
// Returns: PCB * - Success
// NULL - Failure
//
// Description: Given a BCB*, this function will return a pointer to the
// PCB in it with the highest dwSubEntryIndex.
//
PCB * GetPCBPointerFromBCB( IN BCB * pBcb ) { DWORD dwForIndex; PCB * pPcb = NULL; PCB * pPcbTemp; CPCB * pCpCb; DWORD dwSubEntryIndex = 0;
if ( pBcb == NULL ) { return( NULL ); }
for (dwForIndex = 0; dwForIndex < pBcb->dwPpcbArraySize; dwForIndex++) { if ( ( pPcbTemp = pBcb->ppPcb[dwForIndex] ) != NULL ) { pCpCb = GetPointerToCPCB( pPcbTemp, LCP_INDEX ); PPP_ASSERT( NULL != pCpCb );
if ( FSM_OPENED == pCpCb->State ) { if ( pPcbTemp->dwSubEntryIndex >= dwSubEntryIndex ) { pPcb = pPcbTemp; dwSubEntryIndex = pPcbTemp->dwSubEntryIndex; } } } }
return( pPcb ); }
//**
//
// Call: HashPortToBucket
//
// Returns: Index into the PcbTable for the HPORT passed in.
//
// Description: Will hash the HPORT to a bucket index in the PcbTable.
//
DWORD HashPortToBucket( IN HPORT hPort ) { return( (HandleToUlong(hPort)) % PcbTable.NumPcbBuckets ); }
//**
//
// Call: InsertWorkItemInQ
//
// Returns: None.
//
// Description: Inserts a work item in to the work item Q.
//
VOID InsertWorkItemInQ( IN PCB_WORK_ITEM * pWorkItem ) { //
// Take Mutex around work item Q
//
EnterCriticalSection( &(WorkItemQ.CriticalSection) );
if ( WorkItemQ.pQTail != (PCB_WORK_ITEM *)NULL ) { WorkItemQ.pQTail->pNext = pWorkItem; WorkItemQ.pQTail = pWorkItem;
if ( ProcessLineDown == pWorkItem->Process ) { //
// If a lot of work items are coming in, the worker thread may get
// overwhelmed and the following might happen in the work item Q:
// IPCP(port 1)-LineDown(1)-LineUp(1)
// We will send the reply to the IPCP packet to the wrong (ie new)
// peer.
// Proposed solution: Insert a LineDown at the beginning of the
// queue, as well as at the end:
// LineDown(1)-IPCP(port 1)-LineDown(1)-LineUp(1).
// However, this will not take care of the following case:
// IPCP(1)-LD(1)-LU(1)-LCP(1)-LD(1)-LU(1)-LCP(1)
// We transform the above to:
// LD(1)-LD(1)-IPCP(1)-LD(1)-LU(1)-LCP(1)-LD(1)-LU(1)-LCP(1)
// However, the frequency of this problem will be a lot less.
//
PCB_WORK_ITEM * pWorkItem2;
pWorkItem2 = (PCB_WORK_ITEM *)LOCAL_ALLOC( LPTR, sizeof(PCB_WORK_ITEM));
if ( NULL != pWorkItem2 ) { pWorkItem2->hPort = pWorkItem->hPort; pWorkItem2->Process = ProcessLineDown; PppLog( 2, "Inserting extra PPPEMSG_LineDown for hPort=%d", pWorkItem2->hPort );
pWorkItem2->pNext = WorkItemQ.pQHead; WorkItemQ.pQHead = pWorkItem2; } } } else { WorkItemQ.pQHead = pWorkItem; WorkItemQ.pQTail = pWorkItem; }
SetEvent( WorkItemQ.hEventNonEmpty );
LeaveCriticalSection( &(WorkItemQ.CriticalSection) ); }
//**
//
// Call: NotifyCallerOfFailureOnPort
//
// Returns: None
//
// Description: Will notify the caller or initiator of the PPP connection on
// the port about a failure event.
//
VOID NotifyCallerOfFailureOnPort( IN HPORT hPort, IN BOOL fServer, IN DWORD dwRetCode ) { PPP_MESSAGE PppMsg; DWORD dwMsgId = fServer ? PPPDDMMSG_PppFailure : PPPMSG_PppFailure;
ZeroMemory( &PppMsg, sizeof( PppMsg ) );
PppMsg.hPort = hPort; PppMsg.dwMsgId = dwMsgId;
switch( dwMsgId ) { case PPPDDMMSG_PppFailure:
PppMsg.ExtraInfo.DdmFailure.dwError = dwRetCode;
PppConfigInfo.SendPPPMessageToDdm( &PppMsg );
break;
case PPPMSG_PppFailure:
PppMsg.ExtraInfo.Failure.dwError = dwRetCode; PppMsg.ExtraInfo.Failure.dwExtendedError = 0;
RasSendPppMessageToRasman( PppMsg.hPort, (LPBYTE) &PppMsg );
break; }
}
//**
//
// Call: NotifyCallerOfFailure
//
// Returns: None
//
// Description: Will notify the caller or initiator of the PPP connection on
// the port about a failure event.
//
VOID NotifyCallerOfFailure( IN PCB * pPcb, IN DWORD dwRetCode ) { //
// Discard all non-LCP packets
//
pPcb->PppPhase = PPP_LCP;
NotifyCaller( pPcb, ( pPcb->fFlags & PCBFLAG_IS_SERVER ) ? PPPDDMMSG_PppFailure : PPPMSG_PppFailure, &dwRetCode ); }
//**
//
// Call: NotifyCaller
//
// Returns: None.
//
// Description: Will notify the caller or initiater of the PPP connection
// for the port about PPP events on that port.
//
VOID NotifyCaller( IN PCB * pPcb, IN DWORD dwMsgId, IN PVOID pData ) { DWORD dwRetCode; PPP_MESSAGE PppMsg;
ZeroMemory( &PppMsg, sizeof( PppMsg ) );
PppLog( 2, "NotifyCaller(hPort=%d, dwMsgId=%d)", pPcb->hPort, dwMsgId );
PppMsg.hPort = pPcb->hPort; PppMsg.dwMsgId = dwMsgId;
switch( dwMsgId ) { case PPPDDMMSG_Stopped:
if ( !(pPcb->fFlags & PCBFLAG_IS_SERVER) ) { return; }
PppMsg.ExtraInfo.DdmStopped.dwReason = *((DWORD*)pData);
PppConfigInfo.SendPPPMessageToDdm( &PppMsg );
break;
case PPPDDMMSG_PortCleanedUp:
if ( !(pPcb->fFlags & PCBFLAG_IS_SERVER) ) { return; }
PppConfigInfo.SendPPPMessageToDdm( &PppMsg );
break;
case PPPDDMMSG_PppFailure:
if ( !(pPcb->fFlags & PCBFLAG_IS_SERVER) ) { return; }
PppMsg.ExtraInfo.DdmFailure.dwError = *((DWORD*)pData);
if ( pPcb->pBcb->szRemoteUserName[0] != (CHAR)NULL ) { strcpy(PppMsg.ExtraInfo.DdmFailure.szUserName, pPcb->pBcb->szRemoteUserName); } else { PppMsg.ExtraInfo.DdmFailure.szUserName[0] = (CHAR)NULL; }
if ( pPcb->pBcb->szRemoteDomain[0] != (CHAR)NULL ) { strcpy(PppMsg.ExtraInfo.DdmFailure.szLogonDomain, pPcb->pBcb->szRemoteDomain); } else { PppMsg.ExtraInfo.DdmFailure.szLogonDomain[0] = (CHAR)NULL; }
PppConfigInfo.SendPPPMessageToDdm( &PppMsg );
break;
case PPPDDMMSG_NewBundle: case PPPDDMMSG_NewLink:
if ( !(pPcb->fFlags & PCBFLAG_IS_SERVER) ) return;
if ( dwMsgId == PPPDDMMSG_NewBundle ) { PppMsg.ExtraInfo.DdmNewBundle.pClientInterface = GetClientInterfaceInfo( pPcb );
PppMsg.ExtraInfo.DdmNewBundle.pQuarantineIPFilter = NULL; PppMsg.ExtraInfo.DdmNewBundle.pFilter = NULL; PppMsg.ExtraInfo.DdmNewBundle.fQuarantinePresent = FALSE;
if(pPcb->pBcb->InterfaceInfo.IfType != ROUTER_IF_TYPE_FULL_ROUTER) { PBYTE pQuarantineFilter, pFilter;
pQuarantineFilter = RasAuthAttributeGetConcatVendorSpecific( 311, MS_VSA_Quarantine_IP_Filter, pPcb->pAuthenticatorAttributes);
if(NULL != pQuarantineFilter) { MprInfoDuplicate( pQuarantineFilter, &PppMsg.ExtraInfo.DdmNewBundle.pQuarantineIPFilter);
LocalFree(pQuarantineFilter);
PppMsg.ExtraInfo.DdmNewBundle.fQuarantinePresent = TRUE;
pFilter = RasAuthAttributeGetConcatVendorSpecific( 311, MS_VSA_Filter, pPcb->pAuthenticatorAttributes);
if(NULL != pFilter) { MprInfoDuplicate( pFilter, &PppMsg.ExtraInfo.DdmNewBundle.pFilter);
LocalFree(pFilter); } } }
if(!PppMsg.ExtraInfo.DdmNewBundle.fQuarantinePresent) { //
// Check to see if quarantine timeout is present.
//
if(NULL != RasAuthAttributeGetVendorSpecific( 311, MS_VSA_Quarantine_Session_Timeout, pPcb->pAuthenticatorAttributes)) { PppMsg.ExtraInfo.DdmNewBundle.fQuarantinePresent = TRUE; } } }
PppConfigInfo.SendPPPMessageToDdm( &PppMsg );
break;
case PPPDDMMSG_CallbackRequest:
if ( !(pPcb->fFlags & PCBFLAG_IS_SERVER) ) return;
{ PPPDDM_CALLBACK_REQUEST * pPppDdmCallbackRequest = ( PPPDDM_CALLBACK_REQUEST *)pData;
CopyMemory( &(PppMsg.ExtraInfo.CallbackRequest), pPppDdmCallbackRequest, sizeof( PPPDDM_CALLBACK_REQUEST ) );
}
PppConfigInfo.SendPPPMessageToDdm( &PppMsg );
break;
case PPPDDMMSG_PppDone:
if ( !(pPcb->fFlags & PCBFLAG_IS_SERVER) ) return;
PppMsg.ExtraInfo.ProjectionResult = *((PPP_PROJECTION_RESULT*)pData);
PppConfigInfo.SendPPPMessageToDdm( &PppMsg );
break;
case PPPDDMMSG_Authenticated:
//
// Only server wants to know about authentication results.
//
if ( !(pPcb->fFlags & PCBFLAG_IS_SERVER) ) return;
strcpy( PppMsg.ExtraInfo.AuthResult.szUserName, pPcb->pBcb->szRemoteUserName);
strcpy( PppMsg.ExtraInfo.AuthResult.szLogonDomain, pPcb->pBcb->szRemoteDomain );
PppMsg.ExtraInfo.AuthResult.fAdvancedServer = pPcb->fFlags & PCBFLAG_IS_ADVANCED_SERVER;
PppConfigInfo.SendPPPMessageToDdm( &PppMsg );
break;
case PPPMSG_PppDone: case PPPMSG_AuthRetry: case PPPMSG_Projecting: case PPPMSG_CallbackRequest: case PPPMSG_Callback: case PPPMSG_ChangePwRequest: case PPPMSG_LinkSpeed: case PPPMSG_Progress:
if ( pPcb->fFlags & PCBFLAG_IS_SERVER ) return;
RasSendPppMessageToRasman( PppMsg.hPort, (LPBYTE) &PppMsg );
break;
case PPPMSG_Stopped:
if ( pPcb->fFlags & PCBFLAG_IS_SERVER ) return;
PppMsg.dwError = *((DWORD*)pData);
if(pPcb->fFlags & PCBFLAG_RECVD_TERM_REQ) { PppMsg.ExtraInfo.Stopped.dwFlags = PPP_FAILURE_REMOTE_DISCONNECT; } else { PppMsg.ExtraInfo.Stopped.dwFlags = 0; }
RasSendPppMessageToRasman( PppMsg.hPort, (LPBYTE) &PppMsg );
break;
case PPPMSG_PppFailure:
if ( pPcb->fFlags & PCBFLAG_IS_SERVER ) return;
PppMsg.ExtraInfo.Failure.dwError = *((DWORD*)pData); PppMsg.ExtraInfo.Failure.dwExtendedError = 0;
RasSendPppMessageToRasman( PppMsg.hPort, (LPBYTE) &PppMsg );
break;
case PPPMSG_ProjectionResult:
if ( pPcb->fFlags & PCBFLAG_IS_SERVER ) return;
PppMsg.ExtraInfo.ProjectionResult = *((PPP_PROJECTION_RESULT*)pData);
RasSendPppMessageToRasman( PppMsg.hPort, (LPBYTE) &PppMsg );
break;
case PPPMSG_InvokeEapUI:
if ( pPcb->fFlags & PCBFLAG_IS_SERVER ) return;
PppMsg.ExtraInfo.InvokeEapUI = *((PPP_INVOKE_EAP_UI*)pData);
RasSendPppMessageToRasman( PppMsg.hPort, (LPBYTE)&PppMsg );
break;
case PPPMSG_SetCustomAuthData:
if ( pPcb->fFlags & PCBFLAG_IS_SERVER ) return;
PppMsg.ExtraInfo.SetCustomAuthData= *((PPP_SET_CUSTOM_AUTH_DATA*)pData);
RasSendPppMessageToRasman( PppMsg.hPort, (LPBYTE)&PppMsg );
break;
default: PPP_ASSERT( FALSE );
break; }
return; }
//**
//
// Call: LogPPPEvent
//
// Returns: None
//
// Description: Will log a PPP event in the eventvwr.
//
VOID LogPPPEvent( IN DWORD dwEventId, IN DWORD dwData ) { PppLog( 2, "EventLog EventId = %d, error = %d", dwEventId, dwData ); PppLogError( dwEventId, 0, NULL, dwData ); }
//**
//
// Call: GetCpIndexFromProtocol
//
// Returns: Index of the CP with dwProtocol in the CpTable.
// -1 if there is not CP with dwProtocol in CpTable.
//
// Description:
//
DWORD GetCpIndexFromProtocol( IN DWORD dwProtocol ) { DWORD dwIndex;
for ( dwIndex = 0; dwIndex < ( PppConfigInfo.NumberOfCPs + PppConfigInfo.NumberOfAPs ); dwIndex++ ) { if ( CpTable[dwIndex].CpInfo.Protocol == dwProtocol ) return( dwIndex ); }
return( (DWORD)-1 ); }
//**
//
// Call: IsLcpOpened
//
// Returns: TRUE - LCP is in the OPENED state.
// FALSE - Otherwise
//
// Description: Uses the PppPhase value of the PORT_CONTROL_BLOCK to detect
// to see if the LCP layer is in the OPENED state.
//
BOOL IsLcpOpened( PCB * pPcb ) { if ( pPcb->PppPhase == PPP_LCP ) return( FALSE ); else return( TRUE ); }
//**
//
// Call: GetConfiguredInfo
//
// Returns: NO_ERROR - Success
// Non-zero returns - Failure
//
// Description:
//
DWORD GetConfiguredInfo( IN PCB * pPcb, IN DWORD CPIndex, IN OUT PPP_PROJECTION_RESULT * pProjectionResult, OUT BOOL * pfNCPsAreDone ) { DWORD dwIndex; CPCB * pCpCb; DWORD dwRetCode;
pProjectionResult->ip.dwError = ERROR_PPP_NO_PROTOCOLS_CONFIGURED; pProjectionResult->at.dwError = ERROR_PPP_NO_PROTOCOLS_CONFIGURED; pProjectionResult->ipx.dwError = ERROR_PPP_NO_PROTOCOLS_CONFIGURED; pProjectionResult->nbf.dwError = ERROR_PPP_NO_PROTOCOLS_CONFIGURED; pProjectionResult->ccp.dwError = ERROR_PPP_NO_PROTOCOLS_CONFIGURED;
//
// Check to see if we are all done
//
for (dwIndex = LCP_INDEX+1; dwIndex < PppConfigInfo.NumberOfCPs; dwIndex++) { pCpCb = GetPointerToCPCB( pPcb, dwIndex );
if ( pCpCb->fConfigurable ) { if ( pCpCb->NcpPhase == NCP_CONFIGURING ) { return( NO_ERROR ); }
switch( CpTable[dwIndex].CpInfo.Protocol ) { case PPP_IPCP_PROTOCOL:
pProjectionResult->ip.dwError = pCpCb->dwError;
if ( pProjectionResult->ip.dwError == NO_ERROR ) {
/* Assumption is made here that the
** PPP_PROJECTION_RESULT.wszServerAddress field immediately ** follows the PPP_PROJECTION_RESULT.wszAddress field and ** that both fields are 15 + 1 WCHARs long. */
dwRetCode =(CpTable[dwIndex].CpInfo.RasCpGetNegotiatedInfo)( pCpCb->pWorkBuf, &(pProjectionResult->ip));
if ( dwRetCode != NO_ERROR ) { PppLog( 2, "IPCP GetNegotiatedInfo returned %d", dwRetCode );
pCpCb->dwError = dwRetCode;
pCpCb->NcpPhase = NCP_CONFIGURING;
FsmClose( pPcb, dwIndex );
return( ( dwIndex == CPIndex ) ? dwRetCode : NO_ERROR ); }
pPcb->pBcb->nboRemoteAddress = pProjectionResult->ip.dwRemoteAddress;
if ( pProjectionResult->ip.fSendVJHCompression && pProjectionResult->ip.fReceiveVJHCompression ) { pPcb->pBcb->fFlags |= BCBFLAG_IPCP_VJ_NEGOTIATED; } }
break;
case PPP_ATCP_PROTOCOL:
pProjectionResult->at.dwError = pCpCb->dwError;
if ( pProjectionResult->at.dwError == NO_ERROR ) { dwRetCode=(CpTable[dwIndex].CpInfo.RasCpGetNegotiatedInfo)( pCpCb->pWorkBuf, &(pProjectionResult->at) );
if ( dwRetCode != NO_ERROR ) { pCpCb->dwError = dwRetCode;
pCpCb->NcpPhase = NCP_CONFIGURING;
FsmClose( pPcb, dwIndex );
return( ( dwIndex == CPIndex ) ? dwRetCode : NO_ERROR ); } }
break;
case PPP_IPXCP_PROTOCOL:
pProjectionResult->ipx.dwError = pCpCb->dwError;
if ( pProjectionResult->ipx.dwError == NO_ERROR ) { dwRetCode =(CpTable[dwIndex].CpInfo.RasCpGetNegotiatedInfo)( pCpCb->pWorkBuf, &(pProjectionResult->ipx) );
if ( dwRetCode != NO_ERROR ) { pCpCb->dwError = dwRetCode;
pCpCb->NcpPhase = NCP_CONFIGURING;
FsmClose( pPcb, dwIndex );
return( ( dwIndex == CPIndex ) ? dwRetCode : NO_ERROR ); } }
break;
case PPP_CCP_PROTOCOL:
pProjectionResult->ccp.dwError = pCpCb->dwError;
if ( pProjectionResult->ccp.dwError == NO_ERROR ) { dwRetCode= (CpTable[dwIndex].CpInfo.RasCpGetNegotiatedInfo)( pCpCb->pWorkBuf, &(pProjectionResult->ccp));
if ( dwRetCode != NO_ERROR ) { pCpCb->dwError = dwRetCode;
pCpCb->NcpPhase = NCP_CONFIGURING;
FsmClose( pPcb, dwIndex );
return( ( dwIndex == CPIndex ) ? dwRetCode : NO_ERROR ); }
if ( RAS_DEVICE_TYPE( pPcb->dwDeviceType ) != RDT_Tunnel_L2tp ) { DWORD dwEncryptionType;
//
// Not L2TP. In the case of L2TP, we are interested in
// the IpSec encryption, not MPPE.
//
dwEncryptionType = pProjectionResult->ccp.dwSendProtocolData & ( MSTYPE_ENCRYPTION_40 | MSTYPE_ENCRYPTION_40F | MSTYPE_ENCRYPTION_56 | MSTYPE_ENCRYPTION_128 );
switch ( dwEncryptionType ) { case MSTYPE_ENCRYPTION_40: case MSTYPE_ENCRYPTION_40F:
pPcb->pBcb->fFlags |= BCBFLAG_BASIC_ENCRYPTION; break;
case MSTYPE_ENCRYPTION_56:
pPcb->pBcb->fFlags |= BCBFLAG_STRONGER_ENCRYPTION; break;
case MSTYPE_ENCRYPTION_128:
pPcb->pBcb->fFlags |= BCBFLAG_STRONGEST_ENCRYPTION; break; } } }
break;
case PPP_NBFCP_PROTOCOL:
pProjectionResult->nbf.dwError = pCpCb->dwError;
//
// We call this even if we have an error one the client side
// since we need the failure information
//
if ( ( pProjectionResult->nbf.dwError == NO_ERROR ) || ( !( pPcb->fFlags & PCBFLAG_IS_SERVER ) ) ) { dwRetCode=(CpTable[dwIndex].CpInfo.RasCpGetNegotiatedInfo)( pCpCb->pWorkBuf, &(pProjectionResult->nbf) );
if ( dwRetCode != NO_ERROR ) { pCpCb->dwError = dwRetCode;
pCpCb->NcpPhase = NCP_CONFIGURING;
FsmClose( pPcb, dwIndex );
return( ( dwIndex == CPIndex ) ? dwRetCode : NO_ERROR ); } }
break;
default:
break; } } else { //
// The protocol may have been de-configured because CpBegin failed
//
if ( pCpCb->dwError != NO_ERROR ) { switch( CpTable[dwIndex].CpInfo.Protocol ) { case PPP_IPCP_PROTOCOL: pProjectionResult->ip.dwError = pCpCb->dwError; break;
case PPP_ATCP_PROTOCOL: pProjectionResult->at.dwError = pCpCb->dwError; break;
case PPP_IPXCP_PROTOCOL: pProjectionResult->ipx.dwError = pCpCb->dwError; break;
case PPP_NBFCP_PROTOCOL: pProjectionResult->nbf.dwError = pCpCb->dwError; break;
case PPP_CCP_PROTOCOL: pProjectionResult->ccp.dwError = pCpCb->dwError; break;
default: break; } } } }
if ( ( pPcb->fFlags & PCBFLAG_IS_SERVER ) && ( pProjectionResult->nbf.dwError != NO_ERROR )) { //
// If NBF was not configured copy the computername to the wszWksta
// field
//
if ( *(pPcb->pBcb->szComputerName) == (CHAR)NULL ) { pProjectionResult->nbf.wszWksta[0] = (WCHAR)NULL; } else { CHAR chComputerName[NETBIOS_NAME_LEN+1]; memset( chComputerName, ' ', NETBIOS_NAME_LEN ); chComputerName[NETBIOS_NAME_LEN] = (CHAR)NULL;
strcpy( chComputerName, pPcb->pBcb->szComputerName + strlen(MS_RAS_WITH_MESSENGER));
chComputerName[strlen(chComputerName)] = (CHAR)' ';
MultiByteToWideChar( CP_ACP, 0, chComputerName, -1, pProjectionResult->nbf.wszWksta, sizeof( pProjectionResult->nbf.wszWksta )/sizeof(WCHAR));
if ( !memcmp( MS_RAS_WITH_MESSENGER, pPcb->pBcb->szComputerName, strlen( MS_RAS_WITH_MESSENGER ) ) ) { pProjectionResult->nbf.wszWksta[NETBIOS_NAME_LEN-1] = (WCHAR)3; } } }
*pfNCPsAreDone = TRUE;
return( NO_ERROR ); }
//**
//
// Call: AreNCPsDone
//
// Returns: NO_ERROR - Success
// anything else - Failure
//
// Description: If we detect that all configurable NCPs have completed their
// negotiation, then the PPP_PROJECTION_RESULT structure is also
// filled in.
// This is called during the FsmThisLayerFinished or FsmThisLayerUp
// calls for a certain CP. The index of this CP is passed in.
// If any call to that particular CP fails then an error code is
// passed back. If any call to any other CP fails then the error
// is stored in the dwError field for that CP but the return is
// successful. This is done so that the FsmThisLayerFinshed or
// FsmThisLayerUp calls know if they completed successfully for
// that CP or not. Depending on this, the FSM changes the state
// for that CP or not.
//
DWORD AreNCPsDone( IN PCB * pPcb, IN DWORD CPIndex, OUT PPP_PROJECTION_RESULT * pProjectionResult, OUT BOOL * pfNCPsAreDone ) { DWORD dwRetCode;
*pfNCPsAreDone = FALSE;
ZeroMemory( pProjectionResult, sizeof( PPP_PROJECTION_RESULT ) );
dwRetCode = GetConfiguredInfo( pPcb, CPIndex, pProjectionResult, pfNCPsAreDone );
if ( dwRetCode != NO_ERROR ) { return( dwRetCode ); }
if ( !(*pfNCPsAreDone ) ) { return( NO_ERROR ); }
//
// Now get LCP information
//
pProjectionResult->lcp.hportBundleMember = (HPORT)INVALID_HANDLE_VALUE; pProjectionResult->lcp.szReplyMessage = pPcb->pBcb->szReplyMessage;
dwRetCode = (CpTable[LCP_INDEX].CpInfo.RasCpGetNegotiatedInfo)( pPcb->LcpCb.pWorkBuf, &(pProjectionResult->lcp));
if ( RAS_DEVICE_TYPE( pPcb->dwDeviceType ) == RDT_Tunnel_L2tp ) { if ( pPcb->pBcb->fFlags & BCBFLAG_BASIC_ENCRYPTION ) { pProjectionResult->lcp.dwLocalOptions |= PPPLCPO_DES_56; pProjectionResult->lcp.dwRemoteOptions |= PPPLCPO_DES_56; } else if ( pPcb->pBcb->fFlags & BCBFLAG_STRONGEST_ENCRYPTION ) { pProjectionResult->lcp.dwLocalOptions |= PPPLCPO_3_DES; pProjectionResult->lcp.dwRemoteOptions |= PPPLCPO_3_DES; } }
pProjectionResult->lcp.dwLocalEapTypeId = pPcb->dwServerEapTypeId; pProjectionResult->lcp.dwRemoteEapTypeId = pPcb->dwClientEapTypeId;
return( dwRetCode ); }
//**
//
// Call: GetUid
//
// Returns: A BYTE value viz. unique with the 0 - 255 range
//
// Description:
//
BYTE GetUId( IN PCB * pPcb, IN DWORD CpIndex ) { BYTE UId;
//
// For NCPs get the UID from the BCB
//
if ( ( CpIndex != LCP_INDEX ) && ( CpIndex >= PppConfigInfo.NumberOfCPs ) ) { UId = (BYTE)(pPcb->pBcb->UId);
(pPcb->pBcb->UId)++;
return( UId ); }
UId = (BYTE)(pPcb->UId);
(pPcb->UId)++;
return( UId ); }
//**
//
// Call: AlertableWaitForSingleObject
//
// Returns: None
//
// Description: Will wait infintely for a single object in alertable mode. If
// the wait completes because of an IO completion it will
// wait again.
//
VOID AlertableWaitForSingleObject( IN HANDLE hObject ) { DWORD dwRetCode;
do { dwRetCode = WaitForSingleObjectEx( hObject, INFINITE, TRUE );
PPP_ASSERT( dwRetCode != 0xFFFFFFFF ); PPP_ASSERT( dwRetCode != WAIT_TIMEOUT ); } while ( dwRetCode == WAIT_IO_COMPLETION ); }
//**
//
// Call: NotifyIPCPOfNBFCPProjectiont
//
// Returns: TRUE - Success
// FALSE - Failure
//
// Description: Will notify IPCPs of all the configuration information,
// specifically it is looking for NBFCP information.
// Will return FALSE if the IPCP was not notified
// successfully.
//
//
BOOL NotifyIPCPOfNBFCPProjection( IN PCB * pPcb, IN DWORD CpIndex ) { CPCB* pCpCb; DWORD dwRetCode; PPP_PROJECTION_RESULT ProjectionResult; PPPCP_NBFCP_RESULT NbfCpResult; DWORD NBFCPIndex; DWORD IPCPIndex;
NBFCPIndex = GetCpIndexFromProtocol( PPP_NBFCP_PROTOCOL );
IPCPIndex = GetCpIndexFromProtocol( PPP_IPCP_PROTOCOL );
//
// No IPCP installed, we are done
//
if ( IPCPIndex == (DWORD)-1 ) { return( TRUE ); } if ( CpTable[CpIndex].CpInfo.Protocol == PPP_IPCP_PROTOCOL ) { if ( NBFCPIndex != (DWORD)-1 ) { pCpCb = GetPointerToCPCB( pPcb, NBFCPIndex );
if ( pCpCb == NULL ) { return( FALSE ); }
if ( pCpCb->fConfigurable ) { if ( pCpCb->NcpPhase == NCP_CONFIGURING ) { //
// NBFCP is still being configured, we need to wait
// until it is done
//
PppLog( 2, "Waiting for NBFCP to complete" ); return( TRUE ); } } } }
if ( CpTable[CpIndex].CpInfo.Protocol == PPP_NBFCP_PROTOCOL ) { pCpCb = GetPointerToCPCB( pPcb, IPCPIndex );
if ( pCpCb == NULL ) { return( FALSE ); }
if ( pCpCb->fConfigurable ) { if ( pCpCb->NcpPhase == NCP_CONFIGURING ) { //
// IPCP is still being configured, we need to wait
// until it is done
//
PppLog( 2, "Waiting for IPCP to complete" ); return( TRUE ); } } else { //
// IPCP not configurable, we are done.
//
return( TRUE ); } }
//
// If we are here that means we need to notify IPCP of NBFCP projection.
// NBF may or may not be configurable, or may or may not have projected
// successfully
//
ZeroMemory( &ProjectionResult, sizeof( PPP_PROJECTION_RESULT ) );
ZeroMemory( &NbfCpResult, sizeof( NbfCpResult ) );
ProjectionResult.nbf.dwError = ERROR_PPP_NO_PROTOCOLS_CONFIGURED;
if ( NBFCPIndex != (DWORD)-1 ) { pCpCb = GetPointerToCPCB( pPcb, NBFCPIndex );
if ( pCpCb == NULL ) { return( FALSE ); }
if ( pCpCb->fConfigurable ) { if ( ProjectionResult.nbf.dwError == NO_ERROR ) { dwRetCode = (CpTable[NBFCPIndex].CpInfo.RasCpGetNegotiatedInfo)( pCpCb->pWorkBuf, &(ProjectionResult.nbf) );
if ( dwRetCode != NO_ERROR ) { pCpCb->dwError = dwRetCode;
pCpCb->NcpPhase = NCP_CONFIGURING;
FsmClose( pPcb, NBFCPIndex );
return( FALSE ); } } } }
//
// Notify IPCP of NBFCP projection
//
pCpCb = GetPointerToCPCB( pPcb, IPCPIndex );
if ( pCpCb == NULL ) { return( FALSE ); }
dwRetCode = (CpTable[IPCPIndex].CpInfo.RasCpProjectionNotification)( pCpCb->pWorkBuf, (PVOID)&ProjectionResult );
PppLog( 2, "Notifying IPCP of projection notification" );
if ( dwRetCode != NO_ERROR ) { PppLog( 2,"RasIPCPProjectionNotification returned %d", dwRetCode );
pCpCb->dwError = dwRetCode;
pCpCb->NcpPhase = NCP_CONFIGURING;
FsmClose( pPcb, IPCPIndex );
return( FALSE ); }
return( TRUE ); }
//**
//
// Call: CalculateRestartTimer
//
// Returns: The value of the restart timer in seconds based on the link
// speed.
//
// Description: Will get the link speed from rasman and calculate the value
// if the restart timer based on it.
//
DWORD CalculateRestartTimer( IN HPORT hPort ) { RASMAN_INFO RasmanInfo;
if ( RasGetInfo( NULL, hPort, &RasmanInfo ) != NO_ERROR ) { return( PppConfigInfo.DefRestartTimer ); }
if ( RasmanInfo.RI_LinkSpeed <= 1200 ) { return( 7 ); }
if ( RasmanInfo.RI_LinkSpeed <= 2400 ) { return( 5 ); }
if ( RasmanInfo.RI_LinkSpeed <= 9600 ) { return( 3 ); } else { return( 1 ); }
}
//**
//
// Call: CheckCpsForInactivity
//
// Returns: None
//
// Description: Will call each Control protocol to get the time since last
// activity.
//
VOID CheckCpsForInactivity( IN PCB * pPcb, IN DWORD dwEvent //Type of event to check against
) { DWORD dwRetCode; DWORD dwIndex; DWORD dwTimeSinceLastActivity = 0;
PppLog( 2, "Time to check Cps for Activity for port %d", pPcb->hPort );
dwRetCode = RasGetTimeSinceLastActivity( pPcb->hPort, &dwTimeSinceLastActivity );
if ( dwRetCode != NO_ERROR ) { PppLog(2, "RasGetTimeSinceLastActivityTime returned %d\r\n", dwRetCode);
return; }
PppLog(2, "Port %d inactive for %d seconds", pPcb->hPort, dwTimeSinceLastActivity );
//
// If all the stacks have been inactive for at least AutoDisconnectTime
// then we disconnect.
//
if ( dwEvent == TIMER_EVENT_AUTODISCONNECT ) { if ( dwTimeSinceLastActivity >= pPcb->dwAutoDisconnectTime) { PppLog(1,"Disconnecting port %d due to inactivity.", pPcb->hPort);
if ( !( pPcb->fFlags & PCBFLAG_IS_SERVER ) ) { HANDLE hLogHandle;
if( pPcb->pBcb->InterfaceInfo.IfType == ROUTER_IF_TYPE_FULL_ROUTER) { hLogHandle = RouterLogRegisterA( "RemoteAccess" ); } else { hLogHandle = PppConfigInfo.hLogEvents; }
if ( hLogHandle != NULL ) { CHAR * pszPortName = pPcb->szPortName;
RouterLogInformationA( hLogHandle, ROUTERLOG_CLIENT_AUTODISCONNECT, 1, &pszPortName, NO_ERROR );
if ( hLogHandle != PppConfigInfo.hLogEvents ) { RouterLogDeregisterA( hLogHandle ); } } }
//
// Terminate the link
//
pPcb->LcpCb.dwError = ERROR_IDLE_DISCONNECTED;
FsmClose( pPcb, LCP_INDEX ); } else { InsertInTimerQ( pPcb->dwPortId, pPcb->hPort, 0, 0, FALSE, TIMER_EVENT_AUTODISCONNECT, pPcb->dwAutoDisconnectTime - dwTimeSinceLastActivity ); } } //
// Do the LCP Echo request if its pppoe
//
else if ( (RDT_PPPoE == RAS_DEVICE_TYPE(pPcb->dwDeviceType)) && (dwEvent == TIMER_EVENT_LCP_ECHO )) { if ( pPcb->fEchoRequestSend ) { //
// Because the line was inactive for dwEchoTimeout, we send an echo
// request and did not get any response back in 3 seconds after that.
// So we have to disconnect the port.
//
pPcb->dwNumEchoResponseMissed ++; if ( pPcb->dwNumEchoResponseMissed >= pPcb->dwNumMissedEchosBeforeDisconnect ) { PppLog(1,"Missed %d consecutive echo responses. Disconnecting port %d " "due to no echo responses.", pPcb->dwNumMissedEchosBeforeDisconnect, pPcb->hPort); //
// Terminate the link
//
pPcb->LcpCb.dwError = ERROR_IDLE_DISCONNECTED; pPcb->fEchoRequestSend = 0; pPcb->dwNumEchoResponseMissed = 0; FsmClose( pPcb, LCP_INDEX ); } else { //no response yet. So send one more echo request.
FsmSendEchoRequest( pPcb, LCP_INDEX); InsertInTimerQ( pPcb->dwPortId, pPcb->hPort, 0, 0, FALSE, TIMER_EVENT_LCP_ECHO, pPcb->dwLCPEchoTimeInterval ); } } else { //
//No echo request send or we have got a response for echo already
//
//
// check to see if the the inactivity is more than EchoTimeout
//
if ( dwTimeSinceLastActivity >= pPcb->dwIdleBeforeEcho ) { //
// call the lcp cp to make the echo request
//
if ( FsmSendEchoRequest( pPcb, LCP_INDEX) ) { //
// send the echo requesst and set the flag
//
pPcb->fEchoRequestSend = 1; //Setup for next echo request here.
InsertInTimerQ( pPcb->dwPortId, pPcb->hPort, 0, 0, FALSE, TIMER_EVENT_LCP_ECHO, pPcb->dwLCPEchoTimeInterval );
} else { PppLog (1, "Send EchoRequest Failed..."); }
} else { InsertInTimerQ( pPcb->dwPortId, pPcb->hPort, 0, 0, FALSE, TIMER_EVENT_LCP_ECHO, pPcb->dwIdleBeforeEcho - dwTimeSinceLastActivity ); } } } }
//**
//
// Call: GetLocalComputerName
//
// Returns: None
//
// Description: Will get the local computer name. Will also find out if the
// the messenger is running and set the appropriate prefix.
//
VOID GetLocalComputerName( IN OUT LPSTR szComputerName ) { SC_HANDLE ScHandle; SC_HANDLE ScHandleService; SERVICE_STATUS ServiceStatus; CHAR chComputerName[MAX_COMPUTERNAME_LENGTH + 1]; DWORD dwComputerNameLen;
*szComputerName = (CHAR)NULL;
//
// Open the local service control manager
//
ScHandle = OpenSCManager( NULL, NULL, GENERIC_READ );
if ( ScHandle == (SC_HANDLE)NULL ) { return; }
ScHandleService = OpenService( ScHandle, SERVICE_MESSENGER, SERVICE_QUERY_STATUS );
if ( ScHandleService == (SC_HANDLE)NULL ) { CloseServiceHandle( ScHandle ); return; }
if ( !QueryServiceStatus( ScHandleService, &ServiceStatus ) ) { CloseServiceHandle( ScHandle ); CloseServiceHandle( ScHandleService ); return; }
CloseServiceHandle( ScHandle ); CloseServiceHandle( ScHandleService );
if ( ServiceStatus.dwCurrentState == SERVICE_RUNNING ) { strcpy( szComputerName, MS_RAS_WITH_MESSENGER ); } else { strcpy( szComputerName, MS_RAS_WITHOUT_MESSENGER ); }
//
// Get the size of the buffer to hold local computer name
//
dwComputerNameLen = sizeof(chComputerName);
if ( !GetComputerNameA( chComputerName, &dwComputerNameLen ) ) { *szComputerName = (CHAR)NULL; return; } strcpy( szComputerName+strlen(szComputerName), chComputerName );
CharToOemA( szComputerName, szComputerName );
PppLog( 2, "Local identification = %s", szComputerName );
return; }
//**
//
// Call: InitEndpointDiscriminator
//
// Returns: NO_ERROR - Success
// non-zero - Failure
//
// Description: Will obtain a unique end-point discriminator to be used to
// negotiate multi-link. This end-point discrimintator has to
// globally unique to this machine.
//
// We first try to use a Class 3 IEEE 802.1 address of any
// netcard that is in this local machine.
//
// If this fails we use the RPC UUID generator to generate a
// Class 1 discriminator.
//
// If this fails we simply use the local computer name as the
// Class 1 discriminator.
//
// Simply use a random number if all else fails.
//
// NOTE: For now we skip over NwLnkNb because it may return an
// address of 1 and not the real MAC address. There is not way
// in user mode for now to get the address.
//
DWORD InitEndpointDiscriminator( IN OUT BYTE EndPointDiscriminator[] ) { DWORD dwRetCode; LPBYTE pBuffer; DWORD EntriesRead; DWORD TotalEntries; PWCHAR pwChar; DWORD dwIndex; UUID Uuid; DWORD dwComputerNameLen; PWKSTA_TRANSPORT_INFO_0 pWkstaTransport;
//
// Enumerate all the transports used by the local rdr and then get the
// address of the first LAN transport card
//
dwRetCode = NetWkstaTransportEnum( NULL, // Local
0, // Level
&pBuffer, // Output buffer
(DWORD)-1,// Pref. max len
&EntriesRead, &TotalEntries, NULL );
if ( ( dwRetCode == NO_ERROR ) && ( EntriesRead > 0 ) ) { pWkstaTransport = (PWKSTA_TRANSPORT_INFO_0)pBuffer;
while ( EntriesRead-- > 0 ) { if ( !pWkstaTransport->wkti0_wan_ish ) { EndPointDiscriminator[0] = 3; // Class 3
pwChar = pWkstaTransport->wkti0_transport_address;
for ( dwIndex = 0; dwIndex < 6; dwIndex++ ) { EndPointDiscriminator[dwIndex+1] = ( iswalpha( *pwChar ) ? *pwChar-L'A'+10 : *pwChar-L'0' ) * 0x10 + ( iswalpha( *(pwChar+1) ) ? *(pwChar+1)-L'A'+10 : *(pwChar+1)-L'0' );
pwChar++; pwChar++; }
NetApiBufferFree( pBuffer );
return( NO_ERROR ); }
pWkstaTransport++; } }
if ( dwRetCode == NO_ERROR ) { NetApiBufferFree( pBuffer ); }
EndPointDiscriminator[0] = 1; // Class 1
//
// We failed to get the mac address so try to use UUIDGEN to get an unique
// local id
//
dwRetCode = UuidCreate( &Uuid );
if ( ( dwRetCode == RPC_S_UUID_NO_ADDRESS ) || ( dwRetCode == RPC_S_OK ) || ( dwRetCode == RPC_S_UUID_LOCAL_ONLY) ) { HostToWireFormat32( Uuid.Data1, EndPointDiscriminator+1 ); HostToWireFormat16( Uuid.Data2, EndPointDiscriminator+5 ); HostToWireFormat16( Uuid.Data3, EndPointDiscriminator+7 ); CopyMemory( EndPointDiscriminator+9, Uuid.Data4, 8 );
return( NO_ERROR ); }
//
// We failed to get the UUID so simply use the computer name
//
dwComputerNameLen = 20;
if ( !GetComputerNameA( EndPointDiscriminator+1, &dwComputerNameLen ) ) { //
// We failed to get the computer name so use a random number
//
srand( GetCurrentTime() );
HostToWireFormat32( rand(), EndPointDiscriminator+1 ); }
return( NO_ERROR ); }
//**
//
// Call: AllocateAndInitBcb
//
// Returns: NO_ERROR - Success
// Non-zero returns - Failure
//
// Description: Allocates and initializes a Bundle control block
//
DWORD AllocateAndInitBcb( PCB * pPcb ) { DWORD dwIndex; DWORD dwRetCode;
//
// Allocate space for NumberOfNcp - LCP - 1 already in the
// Bcb structure
//
pPcb->pBcb = (BCB *)LOCAL_ALLOC( LPTR, sizeof( BCB ) + ( sizeof( CPCB ) * ( PppConfigInfo.NumberOfCPs - 2 ) ) ); if ( pPcb->pBcb == (BCB *)NULL ) { return( GetLastError() ); }
pPcb->pBcb->dwBundleId = GetNewPortOrBundleId(); pPcb->pBcb->UId = 0; pPcb->pBcb->dwLinkCount = 1; pPcb->pBcb->dwAcctLinkCount = 1; pPcb->pBcb->dwMaxLinksAllowed = 0xFFFFFFFF; pPcb->pBcb->fFlags = 0; pPcb->pBcb->hLicense = INVALID_HANDLE_VALUE; pPcb->pBcb->BapCb.dwId = 0; pPcb->pBcb->hTokenImpersonateUser = INVALID_HANDLE_VALUE; // pPcb->pBcb->chSeed = GEN_RAND_ENCODE_SEED
//
// The most common case is to have no more than 2 links in the bundle.
//
pPcb->pBcb->ppPcb = (PPCB *)LOCAL_ALLOC( LPTR, sizeof( PPCB ) * 2 );
if ( pPcb->pBcb->ppPcb == (PPCB *) NULL ) { LOCAL_FREE( pPcb->pBcb ); pPcb->pBcb = NULL;
return( GetLastError() ); }
pPcb->pBcb->dwPpcbArraySize = 2; pPcb->pBcb->ppPcb[0] = pPcb; pPcb->pBcb->ppPcb[1] = NULL;
for( dwIndex=0; dwIndex < PppConfigInfo.NumberOfCPs-1; dwIndex++ ) { CPCB * pCpCb = &(pPcb->pBcb->CpCb[dwIndex]);
pCpCb->NcpPhase = NCP_DEAD; }
return( NO_ERROR ); }
//**
//
// Call: DeallocateAndRemoveBcbFromTable
//
// Returns: None
//
// Description: Will remove the Bcb from the hash table
//
VOID DeallocateAndRemoveBcbFromTable( IN BCB * pBcb ) { DWORD dwIndex; BCB * pBcbWalker = (BCB *)NULL; BCB * pBcbTemp = (BCB *)NULL;
if ( NULL == pBcb ) { return; }
dwIndex = HashPortToBucket( pBcb->hConnection ); pBcbWalker = PcbTable.BcbBuckets[dwIndex].pBundles; pBcbTemp = pBcbWalker;
while( pBcbTemp != (BCB *)NULL ) { if ( pBcbTemp->hConnection == pBcb->hConnection ) { if ( pBcbTemp == PcbTable.BcbBuckets[dwIndex].pBundles ) { PcbTable.BcbBuckets[dwIndex].pBundles = pBcbTemp->pNext; } else { pBcbWalker->pNext = pBcbTemp->pNext; }
break; }
pBcbWalker = pBcbTemp; pBcbTemp = pBcbWalker->pNext; }
//
// Release the licence if there is one
//
if ( INVALID_HANDLE_VALUE != pBcb->hLicense ) { NtLSFreeHandle( (LS_HANDLE)(pBcb->hLicense) ); }
RtlSecureZeroMemory( pBcb->szPassword, sizeof( pBcb->szPassword ) ); RtlSecureZeroMemory( pBcb->szOldPassword, sizeof( pBcb->szOldPassword ) );
//
// Close the OpenThreadToken() handle obtained from Rasman
//
if ( INVALID_HANDLE_VALUE != pBcb->hTokenImpersonateUser ) { CloseHandle( pBcb->hTokenImpersonateUser ); }
//
// pCustomAuthConnData, pCustomAuthUserData, szPhonebookPath,
// szEntryName, and szServerPhoneNumber are allocated by RasMan
// and MUST be LocalFree'd, not LOCAL_FREE'd.
//
LocalFree( pBcb->pCustomAuthConnData ); LocalFree( pBcb->pCustomAuthUserData ); LocalFree( pBcb->EapUIData.pEapUIData ); LocalFree( pBcb->szPhonebookPath ); LocalFree( pBcb->szEntryName ); LocalFree( pBcb->BapCb.szServerPhoneNumber ); LocalFree( pBcb->BapCb.szClientPhoneNumber ); LocalFree( pBcb->szReplyMessage ); FreePassword(&pBcb->DBPassword); FreePassword(&pBcb->DBOldPassword);
if ( NULL != pBcb->szTextualSid ) { LOCAL_FREE( pBcb->szTextualSid ); }
if ( NULL != pBcb->szRemoteIdentity ) { LOCAL_FREE( pBcb->szRemoteIdentity ); }
if ( NULL != pBcb->ppPcb ) { LOCAL_FREE( pBcb->ppPcb ); }
LOCAL_FREE( pBcb ); }
//**
//
// Call: RemovePcbFromTable
//
// Returns: None
//
// Description: Will remove the Pcb from the hash table
//
VOID RemovePcbFromTable( IN PCB * pPcb ) { DWORD dwIndex = HashPortToBucket( pPcb->hPort ); PCB * pPcbWalker = (PCB *)NULL; PCB * pPcbTemp = (PCB *)NULL;
pPcbWalker = PcbTable.PcbBuckets[dwIndex].pPorts; pPcbTemp = pPcbWalker;
while( pPcbTemp != (PCB *)NULL ) { if ( pPcbTemp->hPort == pPcb->hPort ) { if ( pPcbTemp == PcbTable.PcbBuckets[dwIndex].pPorts ) { PcbTable.PcbBuckets[dwIndex].pPorts = pPcbTemp->pNext; } else { pPcbWalker->pNext = pPcbTemp->pNext; }
break; }
pPcbWalker = pPcbTemp; pPcbTemp = pPcbWalker->pNext; } }
//**
//
// Call: WillPortBeBundled
//
// Returns: TRUE - Port will be bundled after authentication
// FALSE - Port cannot be bundled
//
// Description: Will check to see if the usernames and discriminators match
//
BOOL WillPortBeBundled( IN PCB * pPcb ) { PCB* pPcbWalker; DWORD dwIndex;
//
// Optimization: Have rasman tell PPP that the port will be bundled.
//
//
// Walk thru the list of PCBs
//
for ( dwIndex = 0; dwIndex < PcbTable.NumPcbBuckets; dwIndex++ ) { for ( pPcbWalker = PcbTable.PcbBuckets[dwIndex].pPorts; pPcbWalker != NULL; pPcbWalker = pPcbWalker->pNext ) { //
// Don't bundle a port with itself.
//
if ( pPcbWalker->hPort == pPcb->hPort ) { continue; }
//
// If the current port negotiated MRRU ie multilink.
//
if ( pPcbWalker->fFlags & PCBFLAG_CAN_BE_BUNDLED ) { LCPCB * pLcpCb1 = (LCPCB*)(pPcbWalker->LcpCb.pWorkBuf); LCPCB * pLcpCb2 = (LCPCB*)(pPcb->LcpCb.pWorkBuf);
if ( _stricmp(pPcbWalker->pBcb->szLocalUserName, pPcb->pBcb->szLocalUserName) != 0 ) { //
// Authenticator mismatch, not in our bundle
//
continue; }
if ( ( pLcpCb1->Remote.Work.EndpointDiscr[0] != 0 ) && ( memcmp(pLcpCb1->Remote.Work.EndpointDiscr, pLcpCb2->Remote.Work.EndpointDiscr, sizeof(pLcpCb1->Remote.Work.EndpointDiscr))!=0)) { //
// Discriminator mismatch, not in our bundle
//
continue; }
return( TRUE ); } } }
return( FALSE ); }
//**
//
// Call: CanPortsBeBundled
//
// Returns: TRUE - Ports can be bundled
// FALSE - Ports cannot be bundled
//
// Description: Will check to see if the usernames and discriminators match
//
BOOL CanPortsBeBundled( IN PCB * pPcb1, IN PCB * pPcb2, IN BOOL fCheckPolicy ) { CPCB * pCpCb; LCPCB * pLcpCb1 = (LCPCB*)(pPcb1->LcpCb.pWorkBuf); LCPCB * pLcpCb2 = (LCPCB*)(pPcb2->LcpCb.pWorkBuf);
if ( fCheckPolicy && ( PppConfigInfo.fFlags & PPPCONFIG_FLAG_WKSTA ) && ( pPcb1->fFlags & PCBFLAG_IS_SERVER ) && ( pPcb2->fFlags & PCBFLAG_IS_SERVER ) ) { //
// RAS server policy on workstation. Allow multilinking of devices in
// the same device class only, ie all devices are dial-up, or all
// devices are VPN, or all devices are DCC (direct)
//
if ( ( pPcb1->dwDeviceType & RDT_Tunnel ) != ( pPcb2->dwDeviceType & RDT_Tunnel ) ) { return( FALSE ); }
if ( ( pPcb1->dwDeviceType & RDT_Direct ) != ( pPcb2->dwDeviceType & RDT_Direct ) ) { return( FALSE ); } }
//
// If the current port is in PPP_NCP phase meaning that it is post
// authentication and callback.
//
if ( pPcb1->PppPhase == PPP_NCP ) {
if ( ( _stricmp(pPcb1->pBcb->szLocalUserName, pPcb2->pBcb->szLocalUserName) != 0 )|| ( _stricmp(pPcb1->pBcb->szRemoteUserName, pPcb2->pBcb->szRemoteUserName) != 0 )) { //
// Authenticator mismatch, not in our bundle
//
return( FALSE ); }
if ( ( pLcpCb1->Remote.Work.EndpointDiscr[0] != 0 ) && ( memcmp(pLcpCb1->Remote.Work.EndpointDiscr, pLcpCb2->Remote.Work.EndpointDiscr, sizeof(pLcpCb1->Remote.Work.EndpointDiscr))!=0)) { //
// Discriminator mismatch, not in our bundle
//
return( FALSE ); }
if ( ( pLcpCb1->Local.Work.EndpointDiscr[0] != 0 ) && ( memcmp(pLcpCb1->Local.Work.EndpointDiscr, pLcpCb2->Local.Work.EndpointDiscr, sizeof(pLcpCb1->Local.Work.EndpointDiscr))!=0)) { //
// Discriminator mismatch, not in our bundle
//
return( FALSE ); }
return( TRUE ); }
return( FALSE ); }
//**
//
// Call: TryToBundleWithAnotherLink
//
// Returns: NO_ERROR - Success
// Non-zero returns - Failure
//
// Description: Will search through all the PCBs for a port that can be bundled.
// We follow the criteria specified by RFC 1717.
// phPortMulttlink will point to an HPORT that this port was
// bundled with if this function returns TRUE.
//
// If the link is to be bundled, and its link discriminator is not
// unique, we return a unique discriminator in pwLinkDiscriminator.
//
DWORD TryToBundleWithAnotherLink( IN PCB * pPcb ) { DWORD dwIndex; PCB * pPcbWalker = NULL; BCB * pBcbOld = NULL; DWORD dwRetCode = NO_ERROR; DWORD dwForIndex; PPCB * ppPcb; DWORD CpIndex; CPCB * pCpCb;
pPcb->hportBundleMember = (HPORT)INVALID_HANDLE_VALUE;
//
// Walk thru the list of PCBs
//
for ( dwIndex = 0; dwIndex < PcbTable.NumPcbBuckets; dwIndex++ ) { for( pPcbWalker = PcbTable.PcbBuckets[dwIndex].pPorts; pPcbWalker != NULL; pPcbWalker = pPcbWalker->pNext ) { //
// Don't bundle a port with itself.
//
if ( pPcbWalker->hPort == pPcb->hPort ) { continue; }
//
// If the current port negotiated MRRU ie multilink.
//
if ( ( pPcbWalker->fFlags & PCBFLAG_CAN_BE_BUNDLED ) && ( CanPortsBeBundled( pPcbWalker, pPcb, TRUE ) ) ) { if ( pPcbWalker->pBcb->dwLinkCount >= pPcbWalker->pBcb->dwMaxLinksAllowed ) { dwRetCode = ERROR_PORT_LIMIT_REACHED;
break; }
CpIndex = GetCpIndexFromProtocol( PPP_BACP_PROTOCOL );
if (CpIndex != (DWORD)-1) { pCpCb = GetPointerToCPCB( pPcbWalker, CpIndex );
if ( pCpCb->State != FSM_OPENED && ( pPcb->pBcb->fFlags & BCBFLAG_BAP_REQUIRED )) { PppLog( 1, "BAP is required for this user, but BACP " "is not open. hPort = %d", pPcb->hPort );
dwRetCode = ERROR_BAP_REQUIRED;
break; } }
//
// Either there was no authenticator and no discriminator,or
// there were both and there was match for both. So join the
// bundle in either case.
//
dwRetCode = RasPortBundle( pPcbWalker->hPort, pPcb->hPort );
if ( dwRetCode == NO_ERROR ) { PppLog( 2, "Bundling this link with hPort = %d", pPcbWalker->hPort );
pPcb->hportBundleMember = pPcbWalker->hPort; break; } } }
if ( pPcb->hportBundleMember != (HPORT)INVALID_HANDLE_VALUE ) { break; } }
//
// Bundle the port
//
if ( ( dwRetCode == NO_ERROR ) && ( pPcb->hportBundleMember != (HPORT)INVALID_HANDLE_VALUE ) ) { //This check is added to please prefast
if ( pPcbWalker ) { pPcbWalker->fFlags |= PCBFLAG_IS_BUNDLED; } pPcb->fFlags |= PCBFLAG_IS_BUNDLED;
pBcbOld = pPcb->pBcb;
if ( pPcbWalker ) {
pPcb->pBcb = pPcbWalker->pBcb;
pPcbWalker->hportBundleMember = pPcb->hPort; }
pPcb->pBcb->dwLinkCount++; pPcb->pBcb->dwAcctLinkCount++;
for ( dwForIndex = 0; dwForIndex < pPcb->pBcb->dwPpcbArraySize; dwForIndex++ ) { //
// If there is a free space in the array of back pointers, use it
//
if ( pPcb->pBcb->ppPcb[dwForIndex] == NULL ) { PppLog( 2, "Found slot %d for port %d in BCB back pointer array", dwForIndex, pPcb->hPort ); pPcb->pBcb->ppPcb[dwForIndex] = pPcb; break; } }
if ( dwForIndex == pPcb->pBcb->dwPpcbArraySize ) { //
// The array of back pointers is full. ReAlloc.
//
ppPcb = (PPCB *) LOCAL_REALLOC( pPcb->pBcb->ppPcb, 2 * pPcb->pBcb->dwPpcbArraySize * sizeof( PPCB * ) );
if (ppPcb == NULL) { //
// Can we really assume that pPcb->pBcb->ppPcb will be left
// intact? The documentation for HeapReAlloc does not say so.
//
pPcb->pBcb = pBcbOld; pBcbOld = NULL;
pPcbWalker->pBcb->dwLinkCount--; pPcbWalker->pBcb->dwAcctLinkCount--; pPcb->fFlags &= ~PCBFLAG_IS_BUNDLED;
PppLog( 1, "Couldn't ReAlloc BCB back pointer array for port %d", pPcb->hPort );
dwRetCode = GetLastError(); goto LDone; }
pPcb->pBcb->ppPcb = ppPcb; PppLog( 2, "Found slot %d for port %d in BCB back pointer array after ReAlloc", dwForIndex, pPcb->hPort );
pPcb->pBcb->ppPcb[dwForIndex++] = pPcb; pPcb->pBcb->dwPpcbArraySize *= 2;
//
// We are assuming that the new memory will be zeroed.
//
} }
LDone:
DeallocateAndRemoveBcbFromTable( pBcbOld ); return( dwRetCode );
}
//**
//
// Call: AdjustHTokenImpersonateUser
//
// Returns: VOID
//
// Description: Sets hTokenImpersonateUser in pPcb by finding another link that
// pPcb is capable of bundling with and stealing its
// hTokenImpersonateUser. The original hTokenImpersonateUser may
// be INVALID_HANDLE_VALUE if this link came up because BAP called
// RasDial.
//
VOID AdjustHTokenImpersonateUser( IN PCB * pPcb ) { DWORD dwIndex; PCB* pPcbWalker; HANDLE hToken; HANDLE hTokenDuplicate;
if ( INVALID_HANDLE_VALUE != pPcb->pBcb->hTokenImpersonateUser ) { return; }
for ( dwIndex = 0; dwIndex < PcbTable.NumPcbBuckets; dwIndex++ ) { for( pPcbWalker = PcbTable.PcbBuckets[dwIndex].pPorts; pPcbWalker != NULL; pPcbWalker = pPcbWalker->pNext ) { if ( pPcbWalker->hPort == pPcb->hPort ) { continue; }
hToken = pPcbWalker->pBcb->hTokenImpersonateUser;
//
// If the current port negotiated MRRU ie multilink.
//
if ( ( pPcbWalker->fFlags & PCBFLAG_CAN_BE_BUNDLED ) && ( CanPortsBeBundled( pPcbWalker, pPcb, FALSE ) ) && ( INVALID_HANDLE_VALUE != hToken ) ) { if (DuplicateHandle( GetCurrentProcess(), hToken, GetCurrentProcess(), &hTokenDuplicate, 0, TRUE, DUPLICATE_SAME_ACCESS)) { pPcb->pBcb->hTokenImpersonateUser = hTokenDuplicate; }
return; } } } }
//**
//
// Call: FLinkDiscriminatorIsUnique
//
// Returns: TRUE - Unique Link Discriminator
// FALSE - Non-unique Link Discriminator
//
// Description: Returns TRUE if the link discriminator of the link in pPcb is
// unique with respect to the other links in the same bundle.
// Otherwise, it returns FALSE and sets *pdwLinkDisc to a unique
// value that can be used as link discrim.
//
BOOL FLinkDiscriminatorIsUnique( IN PCB * pPcb, OUT DWORD * pdwLinkDisc ) { DWORD dwForIndex; DWORD dwNewDisc; DWORD dwTempDisc; DWORD fDiscIsUnique = TRUE;
dwNewDisc = ((LCPCB*) (pPcb->LcpCb.pWorkBuf))->Local.Work.dwLinkDiscriminator;
*pdwLinkDisc = 0; // The highest link discriminator seen so far
for ( dwForIndex = 0; dwForIndex < pPcb->pBcb->dwPpcbArraySize; dwForIndex++ ) { if ( ( pPcb->pBcb->ppPcb[dwForIndex] != NULL ) && ( pPcb->pBcb->ppPcb[dwForIndex] != pPcb ) ) { dwTempDisc = ((LCPCB *) (pPcb->pBcb->ppPcb[dwForIndex]->LcpCb.pWorkBuf)) ->Local.Work.dwLinkDiscriminator;
if ( dwTempDisc > *pdwLinkDisc ) { *pdwLinkDisc = dwTempDisc; } if ( dwTempDisc == dwNewDisc ) { fDiscIsUnique = FALSE; } } }
if ( fDiscIsUnique ) { return( TRUE ); } if ( *pdwLinkDisc != 0xFFFF ) { *pdwLinkDisc += 1;
return( FALSE ); }
//
// Find a unique link discriminator
//
for ( dwTempDisc = 0; // A candidate for unique discriminator
dwTempDisc < 0xFFFF; dwTempDisc++ ) { for ( dwForIndex = 0; dwForIndex < pPcb->pBcb->dwPpcbArraySize; dwForIndex++ ) { if ( pPcb->pBcb->ppPcb[dwForIndex] != NULL ) { if ( dwTempDisc == ((LCPCB *) (pPcb->pBcb->ppPcb[dwForIndex]->LcpCb.pWorkBuf)) ->Local.Work.dwLinkDiscriminator ) { break; } } }
if ( dwForIndex == pPcb->pBcb->dwPpcbArraySize ) { *pdwLinkDisc = dwTempDisc;
break; } }
if ( dwTempDisc == 0xFFFF ) { PppLog( 1, "FLinkDiscriminatorIsUnique couldn't find a unique link " "discriminator for port %d", pPcb->hPort ); }
return( FALSE ); }
//**
//
// Call: CreateAccountingAttributes
//
// Returns: VOID
//
// Description:
//
VOID CreateAccountingAttributes( IN PCB * pPcb ) { CHAR szAcctSessionId[20]; CHAR szAcctMultiSessionId[20]; DWORD dwIndex = 0; DWORD dwEncryptionType; BYTE abEncryptionType[6]; DWORD dwRetCode = NO_ERROR; RAS_AUTH_ATTRIBUTE * pAttributes = NULL; RAS_AUTH_ATTRIBUTE * pClassAttribute = NULL; RAS_AUTH_ATTRIBUTE * pFramedRouteAttribute = NULL; RAS_AUTH_ATTRIBUTE * pDomainAttribute = NULL; HANDLE hAttribute; DWORD dwValue; PDSROLE_PRIMARY_DOMAIN_INFO_BASIC pGlobalDomainInfo; LCPCB * pLcpCb = (LCPCB*)(pPcb->LcpCb.pWorkBuf); RasAuthAttributeDestroy( pPcb->pAccountingAttributes );
pPcb->pAccountingAttributes = NULL;
if ( !( pPcb->fFlags & PCBFLAG_IS_SERVER ) ) { return; }
//
// Check to see how many class attributes we have to send if any.
//
if ( pPcb->pAuthProtocolAttributes != NULL ) { pAttributes = pPcb->pAuthProtocolAttributes;
} else if ( pPcb->pAuthenticatorAttributes != NULL ) { pAttributes = pPcb->pAuthenticatorAttributes; }
pClassAttribute = RasAuthAttributeGetFirst( raatClass, pAttributes, &hAttribute );
while( pClassAttribute != NULL ) { dwIndex++;
pClassAttribute = RasAuthAttributeGetNext( &hAttribute, raatClass ); }
//
// Check to see how many Framed-Route attributes we have to send if any.
//
pFramedRouteAttribute = RasAuthAttributeGetFirst( raatFramedRoute, pPcb->pAuthenticatorAttributes, &hAttribute );
while( pFramedRouteAttribute != NULL ) { dwIndex++;
pFramedRouteAttribute = RasAuthAttributeGetNext( &hAttribute, raatFramedRoute ); }
pDomainAttribute = RasAuthAttributeGetVendorSpecific( 311, MS_VSA_CHAP_Domain, //10
pAttributes );
ZeroMemory( szAcctSessionId, sizeof( szAcctSessionId ) );
_itoa(pPcb->dwAccountingSessionId, szAcctSessionId, 10);
ZeroMemory( szAcctMultiSessionId, sizeof( szAcctMultiSessionId ) );
_itoa( pPcb->pBcb->dwBundleId, szAcctMultiSessionId, 10 );
//
// Allocate max total number of attributes that will be used in the
// start and stop accouting messages.
//
pPcb->pAccountingAttributes = RasAuthAttributeCreate( PPP_NUM_ACCOUNTING_ATTRIBUTES + dwIndex );
if ( pPcb->pAccountingAttributes == NULL ) { return; }
do { //
// First insert user attributes
//
for( dwIndex = 0; pPcb->pUserAttributes[dwIndex].raaType != raatMinimum; dwIndex++ ) { dwRetCode = RasAuthAttributeInsert( dwIndex, pPcb->pAccountingAttributes, pPcb->pUserAttributes[dwIndex].raaType, FALSE, pPcb->pUserAttributes[dwIndex].dwLength, pPcb->pUserAttributes[dwIndex].Value );
if ( dwRetCode != NO_ERROR ) { break; } }
if ( dwRetCode != NO_ERROR ) { break; }
//
// Now insert the class attributes if there were any
//
pClassAttribute = RasAuthAttributeGetFirst( raatClass, pAttributes, &hAttribute );
while( pClassAttribute != NULL ) { dwRetCode = RasAuthAttributeInsert( dwIndex++, pPcb->pAccountingAttributes, pClassAttribute->raaType, FALSE, pClassAttribute->dwLength, pClassAttribute->Value );
if ( dwRetCode != NO_ERROR ) { break; }
pClassAttribute = RasAuthAttributeGetNext( &hAttribute, raatClass ); }
if ( dwRetCode != NO_ERROR ) { break; }
//
// Now insert the Framed-Route attributes if there were any
//
pFramedRouteAttribute = RasAuthAttributeGetFirst( raatFramedRoute, pPcb->pAuthenticatorAttributes, &hAttribute );
while( pFramedRouteAttribute != NULL ) { dwRetCode = RasAuthAttributeInsert( dwIndex++, pPcb->pAccountingAttributes, pFramedRouteAttribute->raaType, FALSE, pFramedRouteAttribute->dwLength, pFramedRouteAttribute->Value );
if ( dwRetCode != NO_ERROR ) { break; }
pFramedRouteAttribute = RasAuthAttributeGetNext( &hAttribute, raatFramedRoute ); }
if ( dwRetCode != NO_ERROR ) { break; }
//
// Now insert the domain attribute if there was one
//
if ( pDomainAttribute != NULL ) { dwRetCode = RasAuthAttributeInsert( dwIndex++, pPcb->pAccountingAttributes, pDomainAttribute->raaType, FALSE, pDomainAttribute->dwLength, pDomainAttribute->Value );
if ( dwRetCode != NO_ERROR ) { break; } }
dwRetCode = RasAuthAttributeInsert( dwIndex++, pPcb->pAccountingAttributes, raatAcctSessionId, FALSE, strlen( szAcctSessionId ), szAcctSessionId );
if ( dwRetCode != NO_ERROR ) { break; }
if ( NULL != pPcb->pBcb->szRemoteIdentity ) { dwRetCode = RasAuthAttributeInsert( dwIndex++, pPcb->pAccountingAttributes, raatUserName, FALSE, strlen( pPcb->pBcb->szRemoteIdentity ), pPcb->pBcb->szRemoteIdentity );
if ( dwRetCode != NO_ERROR ) { break; } }
if ( 0 != pPcb->pBcb->nboRemoteAddress ) { dwRetCode = RasAuthAttributeInsert( dwIndex++, pPcb->pAccountingAttributes, raatFramedIPAddress, FALSE, 4, (LPVOID) LongToPtr(ntohl( pPcb->pBcb->nboRemoteAddress )) );
if ( dwRetCode != NO_ERROR ) { break; } }
{ ULONG mru = (pLcpCb->Remote.Work.MRU > LCP_DEFAULT_MRU) ? LCP_DEFAULT_MRU : pLcpCb->Remote.Work.MRU; dwRetCode = RasAuthAttributeInsert( dwIndex++, pPcb->pAccountingAttributes, raatFramedMTU, FALSE, 4, (LPVOID) UlongToPtr(( mru ))); }
if ( dwRetCode != NO_ERROR ) { break; }
if ( pPcb->pBcb->fFlags & BCBFLAG_IPCP_VJ_NEGOTIATED ) { dwRetCode = RasAuthAttributeInsert( dwIndex++, pPcb->pAccountingAttributes, raatFramedCompression, FALSE, 4, (LPVOID) 1 ); // VJ TCP/IP header compression
if ( dwRetCode != NO_ERROR ) { break; } }
if ( pPcb->szCallbackNumber[0] != 0 ) { dwRetCode = RasAuthAttributeInsert( dwIndex++, pPcb->pAccountingAttributes, raatCallbackNumber, FALSE, strlen(pPcb->szCallbackNumber), (LPVOID)pPcb->szCallbackNumber );
if ( dwRetCode != NO_ERROR ) { break; } }
if ( pPcb->dwSessionTimeout > 0 ) { dwRetCode = RasAuthAttributeInsert( dwIndex++, pPcb->pAccountingAttributes, raatSessionTimeout, FALSE, 4, (LPVOID) ULongToPtr(pPcb->dwSessionTimeout) );
if ( dwRetCode != NO_ERROR ) { break; } }
if ( pPcb->dwAutoDisconnectTime > 0 ) { dwRetCode = RasAuthAttributeInsert( dwIndex++, pPcb->pAccountingAttributes, raatIdleTimeout, FALSE, 4, (LPVOID) ULongToPtr(pPcb->dwAutoDisconnectTime) );
if ( dwRetCode != NO_ERROR ) { break; } }
if ( pPcb->pBcb->dwMaxLinksAllowed != 0xFFFFFFFF ) { //
// There is a real limit
//
dwRetCode = RasAuthAttributeInsert( dwIndex++, pPcb->pAccountingAttributes, raatPortLimit, FALSE, 4, (LPVOID) ULongToPtr(pPcb->pBcb->dwMaxLinksAllowed) );
if ( dwRetCode != NO_ERROR ) { break; } }
dwRetCode = RasAuthAttributeInsert( dwIndex++, pPcb->pAccountingAttributes, raatAcctMultiSessionId, FALSE, strlen(szAcctMultiSessionId), (LPVOID)szAcctMultiSessionId );
if ( dwRetCode != NO_ERROR ) { break; }
dwRetCode = RasAuthAttributeInsert( dwIndex++, pPcb->pAccountingAttributes, raatAcctLinkCount, FALSE, 4, (LPVOID)ULongToPtr(pPcb->pBcb->dwAcctLinkCount) );
if ( dwRetCode != NO_ERROR ) { break; }
//
// Insert event timestamp attribute
//
dwRetCode = RasAuthAttributeInsert( dwIndex++, pPcb->pAccountingAttributes, raatAcctEventTimeStamp, FALSE, 4, (LPVOID)ULongToPtr(GetSecondsSince1970()) );
if ( dwRetCode != NO_ERROR ) { break; }
if ( PppConfigInfo.fRadiusAuthenticationUsed ) { dwValue = 1; // RADIUS
} else { dwValue = 0; pGlobalDomainInfo = NULL;
dwRetCode = DsRoleGetPrimaryDomainInformation( NULL, DsRolePrimaryDomainInfoBasic, (PBYTE *)&pGlobalDomainInfo );
if ( NO_ERROR == dwRetCode ) { if ( ( pGlobalDomainInfo->MachineRole == DsRole_RoleMemberServer ) || ( pGlobalDomainInfo->MachineRole == DsRole_RoleMemberWorkstation ) ) { dwValue = 3; // Remote
} else { dwValue = 2; // Local
}
DsRoleFreeMemory(pGlobalDomainInfo); } else { dwRetCode = NO_ERROR; } }
if ( 0 != dwValue ) { dwRetCode = RasAuthAttributeInsert( dwIndex++, pPcb->pAccountingAttributes, raatAcctAuthentic, FALSE, 4, (LPVOID)ULongToPtr(dwValue) );
if ( dwRetCode != NO_ERROR ) { break; } }
//
// Insert encryption attribute
//
dwEncryptionType = 0;
if ( pPcb->pBcb->fFlags & BCBFLAG_BASIC_ENCRYPTION ) { dwEncryptionType = 0x00000002; } else if ( pPcb->pBcb->fFlags & BCBFLAG_STRONGER_ENCRYPTION ) { dwEncryptionType = 0x00000008; } else if ( pPcb->pBcb->fFlags & BCBFLAG_STRONGEST_ENCRYPTION ) { dwEncryptionType = 0x00000004; }
//
// 8 Vendor-Type = MS_MPPE_EncryptionType
//
abEncryptionType[0] = MS_VSA_MPPE_Encryption_Type; abEncryptionType[1] = 6; // Vendor-Length = 6
HostToWireFormat32( dwEncryptionType, abEncryptionType + 2 );
dwRetCode = RasAuthAttributeInsertVSA( dwIndex++, pPcb->pAccountingAttributes, 311, 6, abEncryptionType );
if ( dwRetCode != NO_ERROR ) { break; }
} while( FALSE );
//
// Do not send accounting start if there was any error
//
if ( dwRetCode != NO_ERROR ) { RasAuthAttributeDestroy( pPcb->pAccountingAttributes );
pPcb->pAccountingAttributes = NULL;
return; }
//
// NULL terminate
//
pPcb->pAccountingAttributes[dwIndex].raaType = raatMinimum; pPcb->pAccountingAttributes[dwIndex].dwLength = 0; pPcb->pAccountingAttributes[dwIndex].Value = NULL; }
//**
//
// Call: MakeStartAccountingCall
//
// Returns: NO_ERROR - Success
// Non-zero returns - Failure
//
// Description: Start backend authentication module accounting
//
VOID MakeStartAccountingCall( IN PCB * pPcb ) { LCPCB * pLcpCb = (LCPCB*)(pPcb->LcpCb.pWorkBuf); RAS_AUTH_ATTRIBUTE * pAcctInterimIntervalAttribute = NULL; RAS_AUTH_ATTRIBUTE * pAttributes = NULL;
if ( pPcb->fFlags & PCBFLAG_ACCOUNTING_STARTED ) { //
// Already started
//
return; }
pPcb->fFlags |= PCBFLAG_ACCOUNTING_STARTED;
if ( pLcpCb->Local.Work.AP == 0 ) { //
// If the remote side was not authenticated then do not send an
// accounting request as per RADIUS accounting RFC 2139 sec 5.6.
//
return; }
if ( PppConfigInfo.RasAcctProviderStartAccounting != NULL ) { RAS_AUTH_ATTRIBUTE * pAccountingAttributes;
CreateAccountingAttributes( pPcb );
pAccountingAttributes = RasAuthAttributeCopy( pPcb->pAccountingAttributes );
if ( NULL == pAccountingAttributes ) { return; }
//
// Ref the accounting provider - the ref will be removed
// in StartAccounting code.
//
REF_PROVIDER(g_AcctProv); RtlQueueWorkItem( StartAccounting, pAccountingAttributes, WT_EXECUTEDEFAULT );
if ( pPcb->pAuthProtocolAttributes != NULL ) { pAttributes = pPcb->pAuthProtocolAttributes;
} else if ( pPcb->pAuthenticatorAttributes != NULL ) { pAttributes = pPcb->pAuthenticatorAttributes; }
//
// See if we have to do interim accounting
//
pAcctInterimIntervalAttribute = RasAuthAttributeGet( raatAcctInterimInterval, pAttributes ); if ( pAcctInterimIntervalAttribute != NULL ) { DWORD dwInterimInterval = PtrToUlong(pAcctInterimIntervalAttribute->Value);
if ( dwInterimInterval < 60 ) { dwInterimInterval = 60; }
InsertInTimerQ( pPcb->dwPortId, pPcb->hPort, 0, 0, FALSE, TIMER_EVENT_INTERIM_ACCOUNTING, dwInterimInterval ); } }
return; }
//**
//
// Call: InitializeNCPs
//
// Returns: NO_ERROR
// Non-zero return code.
//
// Description: Will run through and initialize all the NCPs that are enabled
// to run.
//
DWORD InitializeNCPs( IN PCB * pPcb, IN DWORD dwConfigMask ) { DWORD dwIndex; BOOL fInitSuccess = FALSE; DWORD dwRetCode = NO_ERROR;
if ( pPcb->fFlags & PCBFLAG_NCPS_INITIALIZED ) { return( NO_ERROR ); } pPcb->fFlags |= PCBFLAG_NCPS_INITIALIZED;
//
// Initialize all the CPs for this port
//
for( dwIndex=LCP_INDEX+1; dwIndex < PppConfigInfo.NumberOfCPs; dwIndex++ ) { CPCB * pCpCb = GetPointerToCPCB( pPcb, dwIndex );
pCpCb->fConfigurable = FALSE;
if ( !( CpTable[dwIndex].fFlags & PPPCP_FLAG_AVAILABLE ) ) { PppLog( 2, "Will not initialize CP %x", CpTable[dwIndex].CpInfo.Protocol );
continue; }
switch( CpTable[dwIndex].CpInfo.Protocol ) {
case PPP_IPCP_PROTOCOL:
if ( dwConfigMask & PPPCFG_ProjectIp ) { //
// Make sure we have a valid interface handle if we are not
// a client dialing out
//
if ( pPcb->pBcb->InterfaceInfo.IfType != (DWORD)-1 ) { if (pPcb->pBcb->InterfaceInfo.hIPInterface == INVALID_HANDLE_VALUE ) { break; } }
pCpCb->fConfigurable = TRUE;
if ( FsmInit( pPcb, dwIndex ) ) { fInitSuccess = TRUE; } }
break; case PPP_ATCP_PROTOCOL:
if ( dwConfigMask & PPPCFG_ProjectAt ) { pCpCb->fConfigurable = TRUE;
if ( FsmInit( pPcb, dwIndex ) ) { fInitSuccess = TRUE; } }
break;
case PPP_IPXCP_PROTOCOL:
if ( dwConfigMask & PPPCFG_ProjectIpx ) { //
// Make sure we have a valid interface handle if we are not
// a client dialing out
//
if ( pPcb->pBcb->InterfaceInfo.IfType != (DWORD)-1 ) { if ( pPcb->pBcb->InterfaceInfo.hIPXInterface == INVALID_HANDLE_VALUE ) { break; } }
pCpCb->fConfigurable = TRUE;
if ( FsmInit( pPcb, dwIndex ) ) { fInitSuccess = TRUE; } }
break;
case PPP_NBFCP_PROTOCOL:
if ( dwConfigMask & PPPCFG_ProjectNbf ) { //
// If we are not a client dialing in or out do not enable
// NBF
//
if ( ( pPcb->pBcb->InterfaceInfo.IfType != (DWORD)-1 ) && ( pPcb->pBcb->InterfaceInfo.IfType != ROUTER_IF_TYPE_CLIENT )) { break; }
pCpCb->fConfigurable = TRUE;
if ( FsmInit( pPcb, dwIndex ) ) { fInitSuccess = TRUE; } }
break;
case PPP_CCP_PROTOCOL:
pCpCb->fConfigurable = TRUE;
if ( !( FsmInit( pPcb, dwIndex ) ) ) { //
// If encryption failed to initialize and we are forcing
// encryption, then bring down the link
//
if ( dwConfigMask & ( PPPCFG_RequireEncryption | PPPCFG_RequireStrongEncryption ) ) { //
// We need to send an Accounting Stop if RADIUS sends
// an Access Accept but we still drop the line.
//
pPcb->fFlags |= PCBFLAG_SERVICE_UNAVAILABLE;
dwRetCode = ERROR_NO_LOCAL_ENCRYPTION; } }
break;
case PPP_BACP_PROTOCOL:
if ( ( dwConfigMask & PPPCFG_NegotiateBacp ) && ( pPcb->pBcb->fFlags & BCBFLAG_CAN_DO_BAP ) ) { pCpCb->fConfigurable = TRUE;
if ( !( FsmInit( pPcb, dwIndex ) ) ) { pPcb->pBcb->fFlags &= ~BCBFLAG_CAN_DO_BAP; } }
break;
default:
break; }
if ( dwRetCode != NO_ERROR ) { break; } }
//
// If we failed to initialize one of the CPs, or CCP failed to
// initialize and we require encryption, then we fail.
//
if ( ( !fInitSuccess ) || ( dwRetCode != NO_ERROR ) ) { if ( dwRetCode == NO_ERROR ) { dwRetCode = ERROR_PPP_NO_PROTOCOLS_CONFIGURED; }
for(dwIndex=LCP_INDEX+1;dwIndex < PppConfigInfo.NumberOfCPs;dwIndex++) { CPCB * pCpCb = GetPointerToCPCB( pPcb, dwIndex );
if ( pCpCb->fBeginCalled == TRUE ) { if ( pCpCb->pWorkBuf != NULL ) { (CpTable[dwIndex].CpInfo.RasCpEnd)( pCpCb->pWorkBuf );
pCpCb->pWorkBuf = NULL; }
pCpCb->fBeginCalled = FALSE; pCpCb->fConfigurable = FALSE; } } }
return( dwRetCode ); }
//**
//
// Call: GetPointerToCPCB
//
// Returns: Pointer to Control Protocol Control Block
//
// Description: Returns the appropriate pointer for a give CP, will return the
// (first) local side for the AP.
//
CPCB * GetPointerToCPCB( IN PCB * pPcb, IN DWORD CpIndex ) { //
// If the C.P. is LCP or authentication, then return the pointer to the
// Pcb's CPCB
//
if ( CpIndex == (DWORD)-1 ) { return( NULL ); } else if ( CpIndex == LCP_INDEX ) { return( &(pPcb->LcpCb) ); } else if ( CpIndex >= PppConfigInfo.NumberOfCPs ) { if ( CpTable[CpIndex].CpInfo.Protocol == PPP_CBCP_PROTOCOL ) { return( &(pPcb->CallbackCb) ); }
if (CpTable[CpIndex].CpInfo.Protocol == pPcb->AuthenticatorCb.Protocol) { return( &(pPcb->AuthenticatorCb) ); }
if (CpTable[CpIndex].CpInfo.Protocol == pPcb->AuthenticateeCb.Protocol) { return( &(pPcb->AuthenticateeCb) ); } } else { //
// Otherwise for NCPs return the pointer to the Pcb's CPCB in its BCB.
//
return( &(pPcb->pBcb->CpCb[CpIndex-1]) ); }
return( NULL ); }
//**
//
// Call: GetNewPortOrBundleId
//
// Returns: New Id
//
// Description: Simply returns a new Id for a new port or bundle.
//
DWORD GetNewPortOrBundleId( VOID ) { return( PppConfigInfo.PortUIDGenerator++ ); }
//**
//
// Call: QueryBundleNCPSate
//
// Returns: NCP_DEAD
// NCP_CONFIGURING
// NCP_UP
// NCP_DOWN
//
// Description: Will check to see if the NCPs for a certain bundle have
// completed their negotiation, either successfully or not.
// If unsuccessfuly, then the retcode is
// ERROR_PPP_NO_PROTOCOLS_CONFIGURED
//
NCP_PHASE QueryBundleNCPState( IN PCB * pPcb ) { DWORD dwIndex; CPCB * pCpCb; BOOL fOneNcpConfigured = FALSE; BOOL fAllNcpsDead = TRUE;
for (dwIndex = LCP_INDEX+1; dwIndex < PppConfigInfo.NumberOfCPs; dwIndex++) { pCpCb = GetPointerToCPCB( pPcb, dwIndex );
if ( pCpCb->fConfigurable ) { if ( pCpCb->NcpPhase == NCP_CONFIGURING ) { return( NCP_CONFIGURING ); } if ( pCpCb->NcpPhase == NCP_UP ) { fOneNcpConfigured = TRUE; }
if ( pCpCb->NcpPhase != NCP_DEAD ) { fAllNcpsDead = FALSE; } } }
if ( fOneNcpConfigured ) { return( NCP_UP ); }
if ( fAllNcpsDead ) { return( NCP_DEAD ); }
return( NCP_DOWN ); }
//**
//
// Call: NotifyCallerOfBundledProjection
//
// Returns: None
//
// Description: Will notify the caller (i.e. supervisor or rasphone) about
// this link being bundled.
//
//
VOID NotifyCallerOfBundledProjection( IN PCB * pPcb ) { DWORD dwRetCode; PPP_PROJECTION_RESULT ProjectionResult; BOOL fNCPsAreDone = FALSE;
ZeroMemory( &ProjectionResult, sizeof( ProjectionResult ) );
//
// Notify the ras client and the ras server about the
// projections
//
dwRetCode = GetConfiguredInfo( pPcb, 0, // don't care
&ProjectionResult, &fNCPsAreDone );
if ( dwRetCode != NO_ERROR ) { return; }
if ( !fNCPsAreDone ) { return; }
//
// Now get LCP information
//
ProjectionResult.lcp.hportBundleMember = pPcb->hportBundleMember; ProjectionResult.lcp.szReplyMessage = pPcb->pBcb->szReplyMessage;
dwRetCode = (CpTable[LCP_INDEX].CpInfo.RasCpGetNegotiatedInfo)( pPcb->LcpCb.pWorkBuf, &(ProjectionResult.lcp));
if ( RAS_DEVICE_TYPE( pPcb->dwDeviceType ) == RDT_Tunnel_L2tp ) { if ( pPcb->pBcb->fFlags & BCBFLAG_BASIC_ENCRYPTION ) { ProjectionResult.lcp.dwLocalOptions |= PPPLCPO_DES_56; ProjectionResult.lcp.dwRemoteOptions |= PPPLCPO_DES_56; } else if ( pPcb->pBcb->fFlags & BCBFLAG_STRONGEST_ENCRYPTION ) { ProjectionResult.lcp.dwLocalOptions |= PPPLCPO_3_DES; ProjectionResult.lcp.dwRemoteOptions |= PPPLCPO_3_DES; } }
ProjectionResult.lcp.dwLocalEapTypeId = pPcb->dwServerEapTypeId; ProjectionResult.lcp.dwRemoteEapTypeId = pPcb->dwClientEapTypeId;
if ( dwRetCode != NO_ERROR ) { return; }
if ( pPcb->fFlags & PCBFLAG_IS_SERVER ) { NotifyCaller( pPcb, PPPDDMMSG_PppDone, &ProjectionResult ); } else { NotifyCaller( pPcb, PPPMSG_ProjectionResult, &ProjectionResult);
NotifyCaller( pPcb, PPPMSG_PppDone, NULL ); } }
//**
//
// Call: StartNegotiatingNCPs
//
// Returns: None
//
// Description: Will start NCP negogiating for the particular port or bundle
//
VOID StartNegotiatingNCPs( IN PCB * pPcb ) { DWORD dwIndex;
pPcb->PppPhase = PPP_NCP;
for (dwIndex = LCP_INDEX+1; dwIndex < PppConfigInfo.NumberOfCPs; dwIndex++) { CPCB * pCpCb = GetPointerToCPCB( pPcb, dwIndex );
if ( pCpCb->fConfigurable ) { pCpCb->NcpPhase = NCP_CONFIGURING;
FsmOpen( pPcb, dwIndex );
FsmUp( pPcb, dwIndex ); } } }
//**
//
// Call: StartAutoDisconnectForPort
//
// Returns: NO_ERROR - Success
// Non-zero returns - Failure
//
// Description: Will insert an auto disconnect and sesison timeout item in the
// timer Q
//
VOID StartAutoDisconnectForPort( IN PCB * pPcb ) { //
// Do session timeout if there is any
//
if ( pPcb->fFlags & PCBFLAG_IS_SERVER ) { RAS_AUTH_ATTRIBUTE * pAttribute = NULL; RAS_AUTH_ATTRIBUTE * pUserAttributes = ( pPcb->pAuthProtocolAttributes ) ? pPcb->pAuthProtocolAttributes : pPcb->pAuthenticatorAttributes; if((pPcb->pBcb->InterfaceInfo.IfType != ROUTER_IF_TYPE_FULL_ROUTER )&& (0 == (pPcb->pBcb->fFlags & BCBFLAG_QUARANTINE_TIMEOUT))) { //
// Check to see if there is a quarantine-session-timeout
// attribute.
//
pAttribute = RasAuthAttributeGetVendorSpecific( 311, MS_VSA_Quarantine_Session_Timeout, pUserAttributes);
if(pAttribute != NULL) { pPcb->pBcb->dwQuarantineSessionTimeout = WireToHostFormat32(((BYTE*)(pAttribute->Value))+6);
pPcb->pBcb->fFlags |= BCBFLAG_QUARANTINE_TIMEOUT; }
}
if(pPcb->pBcb->fFlags & BCBFLAG_QUARANTINE_TIMEOUT) { //
// Remove any previous session-disconnect time item from the
// queue if there was one.
//
RemoveFromTimerQ( pPcb->dwPortId, 0, 0, FALSE, TIMER_EVENT_SESSION_TIMEOUT );
InsertInTimerQ( pPcb->dwPortId, pPcb->hPort, 0, 0, FALSE, TIMER_EVENT_SESSION_TIMEOUT, pPcb->pBcb->dwQuarantineSessionTimeout );
PppLog(2, "AuthAttribute Quarantine Session Timeout = %d", pPcb->pBcb->dwQuarantineSessionTimeout); }
pAttribute = RasAuthAttributeGet( raatSessionTimeout, pUserAttributes);
if ( pAttribute != NULL ) { pPcb->dwSessionTimeout = PtrToUlong(pAttribute->Value); } else { pPcb->dwSessionTimeout = PppConfigInfo.dwDefaultSessionTimeout; }
PppLog( 2, "AuthAttribute SessionTimeout = %d", pPcb->dwSessionTimeout); if ( (pPcb->dwSessionTimeout > 0) && ( (pPcb->pBcb->fFlags & BCBFLAG_QUARANTINE_TIMEOUT) == 0 )) { //
// Remove any previous session-disconnect time item from the
// queue if there was one.
//
RemoveFromTimerQ( pPcb->dwPortId, 0, 0, FALSE, TIMER_EVENT_SESSION_TIMEOUT );
InsertInTimerQ( pPcb->dwPortId, pPcb->hPort, 0, 0, FALSE, TIMER_EVENT_SESSION_TIMEOUT, pPcb->dwSessionTimeout ); } }
//
// Do not start autodisconnect for router interfaces that have
// dialed in, the router dialing in will take care of this.
//
if ( ( pPcb->fFlags & PCBFLAG_IS_SERVER ) && ( pPcb->pBcb->InterfaceInfo.IfType == ROUTER_IF_TYPE_FULL_ROUTER ) ) { return; }
//
// If the AutoDisconnectTime is not infinte, put a timer
// element on the queue that will wake up in AutoDisconnectTime.
//
if ( pPcb->dwAutoDisconnectTime > 0 ) { PppLog( 2, "Inserting autodisconnect in timer q for port=%d, sec=%d", pPcb->hPort, pPcb->dwAutoDisconnectTime );
//
// Remove any previous auto-disconnect time item from the
// queue if there was one.
//
RemoveFromTimerQ( pPcb->dwPortId, 0, 0, FALSE, TIMER_EVENT_AUTODISCONNECT);
InsertInTimerQ( pPcb->dwPortId, pPcb->hPort, 0, 0, FALSE, TIMER_EVENT_AUTODISCONNECT, pPcb->dwAutoDisconnectTime ); } }
//**
//
// Call: StartLCPEchoForPort
//
// Returns: None
//
//
// Description: Will insert an LCPEcho item in the timer Q
//
VOID StartLCPEchoForPort( IN PCB * pPcb ) { if ( !(pPcb->fFlags & PCBFLAG_IS_SERVER) ) { //if this is a client.
//check to see if the connection type is broadband - PPPOE in particular
if ( (RAS_DEVICE_TYPE(pPcb->dwDeviceType) == RDT_PPPoE) && pPcb->dwIdleBeforeEcho ) { PppLog( 2, "LCPEchoTimeout = %d", pPcb->dwIdleBeforeEcho); pPcb->fEchoRequestSend = 0; pPcb->dwNumEchoResponseMissed = 0; //No responses missed yet
InsertInTimerQ( pPcb->dwPortId, pPcb->hPort, 0, 0, FALSE, TIMER_EVENT_LCP_ECHO, pPcb->dwIdleBeforeEcho ); } } return; }
//**
//
// Call: NotifyCompletionOnBundledPorts
//
// Returns: NO_ERROR - Success
// Non-zero returns - Failure
//
// Description: Will notify all ports that are bundled with this port and
// are waiting to for negotiation to complete on the bundle.
//
VOID NotifyCompletionOnBundledPorts( IN PCB * pPcb ) { DWORD dwIndex; PCB * pPcbWalker;
//
// Walk thru the list of PCBs
//
for ( dwIndex = 0; dwIndex < PcbTable.NumPcbBuckets; dwIndex++ ) { for( pPcbWalker = PcbTable.PcbBuckets[dwIndex].pPorts; pPcbWalker != NULL; pPcbWalker = pPcbWalker->pNext ) { if ( ( pPcbWalker->hPort != pPcb->hPort ) && ( pPcbWalker->fFlags & PCBFLAG_IS_BUNDLED ) && ( CanPortsBeBundled( pPcbWalker, pPcb, TRUE ) ) ) { //
// In our bundle so notify the caller of completion on this
// port.
//
RemoveFromTimerQ( pPcbWalker->dwPortId, 0, 0, FALSE, TIMER_EVENT_NEGOTIATETIME );
NotifyCallerOfBundledProjection( pPcbWalker );
StartAutoDisconnectForPort( pPcbWalker ); } } } }
//**
//
// Call: RemoveNonNumerals
//
// Returns: VOID
//
// Description: Removes any character that is not an ASCII digit from
// the string szString
//
VOID RemoveNonNumerals( IN CHAR* szString ) { CHAR c; DWORD dwIndexOld; DWORD dwIndexNew;
if (NULL == szString) { return; }
for (dwIndexOld = 0, dwIndexNew = 0; (c = szString[dwIndexOld]) != 0; dwIndexOld++) { if (isdigit(c)) { szString[dwIndexNew++] = c; } }
szString[dwIndexNew] = 0; }
//**
//
// Call: GetTextualSid
//
// Returns: TRUE - Success
// FALSE - Failure
//
// Description: The GetTextualSid function will convert a binary Sid to a
// textual string. Obtained from the Knowledge Base.
// Article ID: Q131320
//
BOOL GetTextualSid( IN PSID pSid, // binary Sid
OUT CHAR* TextualSid, // buffer for Textual representaion of Sid
IN LPDWORD dwBufferLen // required/provided TextualSid buffersize
) { PSID_IDENTIFIER_AUTHORITY psia; DWORD dwSubAuthorities; DWORD dwSidRev=SID_REVISION; DWORD dwCounter; DWORD dwSidSize;
//
// test if Sid passed in is valid
//
if(!IsValidSid(pSid)) return FALSE;
//
// obtain SidIdentifierAuthority
//
psia=GetSidIdentifierAuthority(pSid);
//
// obtain sidsubauthority count
//
dwSubAuthorities=*GetSidSubAuthorityCount(pSid);
//
// compute buffer length
// S-SID_REVISION- + identifierauthority- + subauthorities- + NULL
//
dwSidSize=(15 + 12 + (12 * dwSubAuthorities) + 1) * sizeof(TCHAR);
//
// check provided buffer length.
// If not large enough, indicate proper size and setlasterror
//
if (*dwBufferLen < dwSidSize) { *dwBufferLen = dwSidSize; SetLastError(ERROR_INSUFFICIENT_BUFFER); return FALSE; }
//
// prepare S-SID_REVISION-
//
dwSidSize=wsprintfA(TextualSid, "S-%lu-", dwSidRev );
//
// prepare SidIdentifierAuthority
//
if ( (psia->Value[0] != 0) || (psia->Value[1] != 0) ) { dwSidSize+=wsprintfA(TextualSid + lstrlenA(TextualSid), "0x%02hx%02hx%02hx%02hx%02hx%02hx", (USHORT)psia->Value[0], (USHORT)psia->Value[1], (USHORT)psia->Value[2], (USHORT)psia->Value[3], (USHORT)psia->Value[4], (USHORT)psia->Value[5]); } else { dwSidSize+=wsprintfA(TextualSid + lstrlenA(TextualSid), "%lu", (ULONG)(psia->Value[5] ) + (ULONG)(psia->Value[4] << 8) + (ULONG)(psia->Value[3] << 16) + (ULONG)(psia->Value[2] << 24) ); }
//
// loop through SidSubAuthorities
//
for (dwCounter=0 ; dwCounter < dwSubAuthorities ; dwCounter++) { dwSidSize+=wsprintfA(TextualSid + dwSidSize, "-%lu", *GetSidSubAuthority(pSid, dwCounter) ); }
return TRUE; }
//**
//
// Call: TextualSidFromPid
//
// Returns: NULL - Failure
// non-NULL - Success
//
// Description: Will LOCAL_ALLOC a Textual Sid for a user whose pid is dwPid.
//
CHAR* TextualSidFromPid( DWORD dwPid ) { #define BUF_SIZE 256
BOOL fFreeTextualSid = FALSE; CHAR* szTextualSid = NULL; HANDLE ProcessHandle = NULL; HANDLE TokenHandle = INVALID_HANDLE_VALUE;
TOKEN_USER ptgUser[BUF_SIZE]; DWORD cbBuffer; DWORD cbSid;
szTextualSid = LOCAL_ALLOC( LPTR, sizeof( CHAR ) * BUF_SIZE );
if ( NULL == szTextualSid ) { BapTrace( "LOCAL_ALLOC() returned error %d", GetLastError() ); goto LDone; }
fFreeTextualSid = TRUE;
ProcessHandle = OpenProcess( PROCESS_ALL_ACCESS, FALSE /* bInheritHandle */, dwPid );
if ( NULL == ProcessHandle ) { BapTrace( "OpenProcess() returned error %d", GetLastError() ); goto LDone; }
if ( !OpenProcessToken( ProcessHandle, TOKEN_QUERY, &TokenHandle ) ) { BapTrace( "OpenProcessToken() returned error %d", GetLastError() ); goto LDone; }
cbBuffer = BUF_SIZE;
if ( !GetTokenInformation( TokenHandle, TokenUser, ptgUser, cbBuffer, &cbBuffer ) ) // Look at KB article Q131320
{ BapTrace( "GetTokenInformation() returned error %d", GetLastError() ); goto LDone; }
cbSid = BUF_SIZE;
if ( !GetTextualSid( ptgUser->User.Sid, szTextualSid, &cbSid ) ) { BapTrace( "GetTextualSid() returned error %d", GetLastError() ); goto LDone; }
fFreeTextualSid = FALSE;
LDone:
if ( NULL != ProcessHandle ) { CloseHandle( ProcessHandle ); }
if ( INVALID_HANDLE_VALUE != TokenHandle ) { CloseHandle( TokenHandle ); }
if ( fFreeTextualSid ) { LOCAL_FREE( szTextualSid ); szTextualSid = NULL; }
return( szTextualSid ); }
//**
//
// Call: GetRouterPhoneBook
//
// Returns: NO_ERROR - Success
// Non-zero returns - Failure
//
// Description: Will LocalAlloc and set pszPhonebookPath to point to the
// full path of the router phonebook.
//
DWORD GetRouterPhoneBook( CHAR** pszPhonebookPath ) { DWORD dwSize; DWORD cchDir = GetWindowsDirectoryA( NULL, 0 ); CHAR* szPhonebookPath;
*pszPhonebookPath = NULL;
if ( cchDir == 0 ) { return( GetLastError() ); }
dwSize=(cchDir+lstrlenA("\\system32\\ras\\router.pbk")+1)*sizeof(CHAR);
if ( ( szPhonebookPath = LocalAlloc( LPTR, dwSize ) ) == NULL ) { return( GetLastError() ); }
if ( GetWindowsDirectoryA( szPhonebookPath, cchDir ) == 0 ) { LocalFree( szPhonebookPath ); return( GetLastError() ); }
if ( szPhonebookPath[cchDir-1] != '\\' ) { lstrcatA( szPhonebookPath, "\\" ); }
lstrcatA( szPhonebookPath, "system32\\ras\\router.pbk" );
*pszPhonebookPath = szPhonebookPath; return( NO_ERROR ); }
//**
//
// Call: GetCredentialsFromInterface
//
// Returns: NO_ERROR - Success
// Non-zero returns - Failure
//
// Description: Get the credentials for the interface called
// pPcb->pBcb->szRemoteUserName.
//
DWORD GetCredentialsFromInterface( PCB * pPcb ) { WCHAR wchUserName[UNLEN+1]; WCHAR wchPassword[PWLEN+1]; WCHAR wchDomainName[DNLEN+1]; WCHAR wchInterfaceName[UNLEN+1]; DWORD dwRetCode;
wchUserName[0] = wchPassword[0] = wchDomainName[0] = wchInterfaceName[0] = 0;
if ( 0 == MultiByteToWideChar( CP_ACP, 0, pPcb->pBcb->szRemoteUserName, -1, wchInterfaceName, sizeof( wchInterfaceName ) / sizeof( WCHAR ) ) ) { dwRetCode = GetLastError();
return( dwRetCode ); }
dwRetCode = MprAdminInterfaceGetCredentialsInternal( NULL, wchInterfaceName, wchUserName, wchPassword, wchDomainName );
if ( NO_ERROR == dwRetCode ) { if ( 0 == WideCharToMultiByte( CP_ACP, 0, wchUserName, -1, pPcb->pBcb->szLocalUserName, sizeof( pPcb->pBcb->szLocalUserName ), NULL, NULL ) ) { dwRetCode = GetLastError();
goto done; }
if ( 0 == WideCharToMultiByte( CP_ACP, 0, wchPassword, -1, pPcb->pBcb->szPassword, sizeof( pPcb->pBcb->szPassword ), NULL, NULL ) ) { dwRetCode = GetLastError();
goto done; }
if ( 0 == WideCharToMultiByte( CP_ACP, 0, wchDomainName, -1, pPcb->pBcb->szLocalDomain, sizeof( pPcb->pBcb->szLocalDomain ), NULL, NULL ) ) { dwRetCode = GetLastError();
goto done; }
// EncodePw( pPcb->pBcb->chSeed, pPcb->pBcb->szPassword );
// EncodePw( pPcb->pBcb->chSeed, pPcb->pBcb->szOldPassword );
dwRetCode = EncodePassword(strlen(pPcb->pBcb->szPassword) + 1, pPcb->pBcb->szPassword, &pPcb->pBcb->DBPassword);
if(NO_ERROR != dwRetCode) { goto done; } }
done:
//
// Null out password buffer
//
RtlSecureZeroMemory( wchPassword, (PWLEN + 1) * sizeof(WCHAR));
//
// wipe out password field in bcb. DBPassword field
// now has the encrypted password.
//
RtlSecureZeroMemory(pPcb->pBcb->szPassword, PWLEN + 1);
return( dwRetCode ); }
//**
//
// Call: IsCpIndexOfAp
//
// Returns: TRUE - The CpIndex belongs to an Authentication Protocol
// FALSE - Otherwise
//
// Description:
//
BOOL IsCpIndexOfAp( IN DWORD CpIndex ) { if ( CpIndex >= PppConfigInfo.NumberOfCPs ) { return( TRUE ); }
return( FALSE ); }
//**
//
// Call: StartAccounting
//
// Returns: None
//
// Description: Will start accounting if the back-end authentication provider
// supports it.
//
VOID StartAccounting( PVOID pContext ) { DWORD dwRetCode; RAS_AUTH_ATTRIBUTE * pInAttributes = (RAS_AUTH_ATTRIBUTE*)pContext; RAS_AUTH_ATTRIBUTE * pOutAttributes = NULL;
dwRetCode = (*PppConfigInfo.RasAcctProviderStartAccounting)( pInAttributes, &pOutAttributes );
if ( pOutAttributes != NULL ) { PppConfigInfo.RasAuthProviderFreeAttributes( pOutAttributes ); }
RasAuthAttributeDestroy( pInAttributes );
DEREF_PROVIDER(g_AcctProv); }
//**
//
// Call: InterimAccounting
//
// Returns: None
//
// Description: Will send and interim accounting packet if the back-end
// authentication provider supports it.
//
VOID InterimAccounting( PVOID pContext ) { DWORD dwRetCode; RAS_AUTH_ATTRIBUTE * pInAttributes = (RAS_AUTH_ATTRIBUTE*)pContext; RAS_AUTH_ATTRIBUTE * pOutAttributes = NULL;
dwRetCode = (*PppConfigInfo.RasAcctProviderInterimAccounting)( pInAttributes, &pOutAttributes );
if ( pOutAttributes != NULL ) { PppConfigInfo.RasAuthProviderFreeAttributes( pOutAttributes ); }
RasAuthAttributeDestroy( pInAttributes );
DEREF_PROVIDER(g_AcctProv); }
//**
//
// Call: StopAccounting
//
// Returns: None
//
// Description: Will stop accounting if the back-end authentication provider
// supports it.
//
VOID StopAccounting( PVOID pContext ) { DWORD dwRetCode; PSTOP_ACCOUNTING_CONTEXT pAcctContext = (PSTOP_ACCOUNTING_CONTEXT)pContext; RAS_AUTH_ATTRIBUTE * pInAttributes = pAcctContext->pAuthAttributes; RAS_AUTH_ATTRIBUTE * pOutAttributes = NULL; PPPE_MESSAGE PppMessage;
//
// It is possible that StopAccounting will be queued on a worker thread
// soon after a StartAccounting (Win2000 bug 376334). We don't want the
// StopAccounting to finish before the StartAccounting. Hence the sleep.
// The real fix is to make sure that the same thread calls both
// StartAccounting and StopAccounting.
//
PppLog ( 2, "Stopping Accounting for port %d", pAcctContext->pPcb->hPort ); Sleep( 2000 );
dwRetCode = (*PppConfigInfo.RasAcctProviderStopAccounting)( pInAttributes, &pOutAttributes );
if ( pOutAttributes != NULL ) { PppConfigInfo.RasAuthProviderFreeAttributes( pOutAttributes ); }
RasAuthAttributeDestroy( pInAttributes );
ZeroMemory ( &PppMessage, sizeof(PppMessage));
PppMessage.hPort = pAcctContext->pPcb->hPort; PppMessage.dwMsgId = PPPEMSG_PostLineDown; PppMessage.ExtraInfo.PostLineDown.pPcb = (VOID *)pAcctContext->pPcb; //Call PostLineDown
SendPPPMessageToEngine( &PppMessage ); LocalFree(pAcctContext);
DEREF_PROVIDER(g_AcctProv); }
//**
//
// Call: StripCRLF
//
// Returns: Strips out CR and LF characters from the string
//
// Description:
//
VOID StripCRLF( CHAR* psz ) { DWORD dw1; DWORD dw2; CHAR ch;
if ( NULL == psz ) { return; }
dw1 = 0; dw2 = 0;
while ( ( ch = psz[dw1++] ) != 0 ) { if ( ( ch == 0xD ) || ( ch == 0xA ) ) { //
// Don't copy this character
//
continue; }
psz[dw2++] = ch; }
psz[dw2] = 0; }
//**
//
// Call: GetUserAttributes
//
// Returns: NO_ERROR - Success
// Non-zero returns - Failure
//
// Description:
//
RAS_AUTH_ATTRIBUTE * GetUserAttributes( PCB * pPcb ) { RAS_AUTH_ATTRIBUTE * pAttributes = NULL; DWORD dwRetCode = NO_ERROR; DWORD dwIndex = 0; RAS_CONNECT_INFO * pConnectInfo = NULL; DWORD dwSize = 0; DWORD dwNASPortType = (DWORD)-1; DWORD dwValue; BOOL fTunnel = FALSE;
if ( pPcb->pUserAttributes != NULL ) { return( NULL ); }
pAttributes = RasAuthAttributeCreate( PPP_NUM_USER_ATTRIBUTES );
if ( pAttributes == NULL ) { return( NULL ); }
do { if ( PppConfigInfo.szNASIdentifier[0] != 0 ) { dwRetCode = RasAuthAttributeInsert( dwIndex++, pAttributes, raatNASIdentifier, FALSE, strlen( PppConfigInfo.szNASIdentifier ), (LPVOID)PppConfigInfo.szNASIdentifier );
if ( dwRetCode != NO_ERROR ) { break; } }
if ( PppConfigInfo.dwNASIpAddress != 0 ) { dwRetCode = RasAuthAttributeInsert( dwIndex++, pAttributes, raatNASIPAddress, FALSE, 4, (LPVOID)ULongToPtr(PppConfigInfo.dwNASIpAddress) ); }
if ( dwRetCode != NO_ERROR ) { break; }
dwRetCode = RasAuthAttributeInsert( dwIndex++, pAttributes, raatServiceType, FALSE, 4, UlongToPtr ( ( pPcb->fFlags & PCBFLAG_THIS_IS_A_CALLBACK ) ? 4 : // Callback Framed
2 ) ); // Framed
if ( dwRetCode != NO_ERROR ) { break; }
dwRetCode = RasAuthAttributeInsert( dwIndex++, pAttributes, raatFramedProtocol, FALSE, 4, (LPVOID)1 ); //PPP
if ( dwRetCode != NO_ERROR ) { break; }
dwRetCode = RasAuthAttributeInsert( dwIndex++, pAttributes, raatNASPort, FALSE, 4, (LPVOID)pPcb->hPort ); if ( dwRetCode != NO_ERROR ) { break; }
{ BYTE MSRASVendor[10]; BYTE MSRASVersion[30]; BYTE bLength;
HostToWireFormat32( 311, MSRASVendor ); // Vendor-Id
MSRASVendor[4] = MS_VSA_RAS_Vendor; //9 Vendor-Type: MS-RAS-Vendor
MSRASVendor[5] = 6; // Vendor-Length
HostToWireFormat32( 311, MSRASVendor + 6) ; // Vendor-Id
dwRetCode = RasAuthAttributeInsert( dwIndex++, pAttributes, raatVendorSpecific, FALSE, 10, MSRASVendor ); if ( dwRetCode != NO_ERROR ) { break; }
bLength = (BYTE)strlen( MS_RAS_VERSION ); RTASSERT( 30 >= 6 + bLength );
HostToWireFormat32( 311, MSRASVersion ); // Vendor-Id
MSRASVersion[4] = MS_VSA_RAS_Version; //18 Vendor-Type: MS-RAS-Version
MSRASVersion[5] = 2 + bLength; // Vendor-Length
CopyMemory( MSRASVersion + 6, MS_RAS_VERSION, bLength );
dwRetCode = RasAuthAttributeInsert( dwIndex++, pAttributes, raatVendorSpecific, FALSE, 6 + bLength, MSRASVersion ); if ( dwRetCode != NO_ERROR ) { break; } }
switch( RAS_DEVICE_TYPE( pPcb->dwDeviceType ) ) { case RDT_Modem: case RDT_Serial: dwNASPortType = 0; break;
case RDT_Isdn: dwNASPortType = 2; break;
case RDT_Tunnel_Pptp: case RDT_Tunnel_L2tp: dwNASPortType = 5; fTunnel = TRUE; break;
default: dwNASPortType = (DWORD)-1; break; }
if ( dwNASPortType != (DWORD)-1 ) { dwRetCode = RasAuthAttributeInsert( dwIndex++, pAttributes, raatNASPortType, FALSE, 4, (LPVOID)ULongToPtr(dwNASPortType) ); if ( dwRetCode != NO_ERROR ) { break; } }
if ( fTunnel ) { dwValue = 0; ((BYTE*)(&dwValue))[0] = ( RAS_DEVICE_TYPE( pPcb->dwDeviceType ) == RDT_Tunnel_Pptp ) ? 1 : 3;
dwRetCode = RasAuthAttributeInsert( dwIndex++, pAttributes, raatTunnelType, FALSE, 4, (LPVOID)ULongToPtr(dwValue) );
if ( dwRetCode != NO_ERROR ) { break; }
dwRetCode = RasAuthAttributeInsert( dwIndex++, pAttributes, raatTunnelMediumType, FALSE, 4, (LPVOID)1 ); // IP
if ( dwRetCode != NO_ERROR ) { break; } }
if ( ( pPcb->fFlags & PCBFLAG_IS_SERVER ) && ( pPcb->fFlags & PCBFLAG_THIS_IS_A_CALLBACK ) ) { //
// send the calling-station-id attrib with the number dialed
//
dwRetCode = RasAuthAttributeInsert( dwIndex++, pAttributes, raatCallingStationId, FALSE, strlen( pPcb->szCallbackNumber ), (VOID*) pPcb->szCallbackNumber );
if ( dwRetCode != NO_ERROR ) { break; } }
if ( RasGetConnectInfo( pPcb->hPort, &dwSize, NULL ) == ERROR_BUFFER_TOO_SMALL ) { if ( ( pConnectInfo = LOCAL_ALLOC( LPTR, dwSize ) ) != NULL ) { if ( RasGetConnectInfo( pPcb->hPort, &dwSize, pConnectInfo ) == NO_ERROR ) { if ( ( pConnectInfo->dwCalledIdSize > 0 ) && ( pConnectInfo->pszCalledId[0] != 0 ) ) { dwRetCode = RasAuthAttributeInsert( dwIndex++, pAttributes, raatCalledStationId, FALSE, strlen(pConnectInfo->pszCalledId), (LPVOID)pConnectInfo->pszCalledId );
if ( dwRetCode != NO_ERROR ) { break; }
if ( fTunnel ) { dwRetCode = RasAuthAttributeInsert( dwIndex++, pAttributes, raatTunnelServerEndpoint, FALSE, strlen(pConnectInfo->pszCalledId), (LPVOID)pConnectInfo->pszCalledId );
if ( dwRetCode != NO_ERROR ) { break; } } } else if ( ( pConnectInfo->dwAltCalledIdSize > 0 ) && ( pConnectInfo->pszAltCalledId[0] != 0 ) ) { dwRetCode = RasAuthAttributeInsert( dwIndex++, pAttributes, raatCalledStationId, FALSE, strlen(pConnectInfo->pszAltCalledId), (LPVOID)pConnectInfo->pszAltCalledId );
if ( dwRetCode != NO_ERROR ) { break; }
if ( fTunnel ) { dwRetCode = RasAuthAttributeInsert( dwIndex++, pAttributes, raatTunnelServerEndpoint, FALSE, strlen(pConnectInfo->pszAltCalledId), (LPVOID)pConnectInfo->pszAltCalledId );
if ( dwRetCode != NO_ERROR ) { break; } } }
if ( ( pConnectInfo->dwCallerIdSize > 0 ) && ( pConnectInfo->pszCallerId[0] != 0 ) ) { dwRetCode = RasAuthAttributeInsert( dwIndex++, pAttributes, raatCallingStationId, FALSE, strlen(pConnectInfo->pszCallerId), (LPVOID)pConnectInfo->pszCallerId );
if ( dwRetCode != NO_ERROR ) { break; }
if ( fTunnel ) { dwRetCode = RasAuthAttributeInsert( dwIndex++, pAttributes, raatTunnelClientEndpoint, FALSE, strlen(pConnectInfo->pszCallerId), (LPVOID)pConnectInfo->pszCallerId );
if ( dwRetCode != NO_ERROR ) { break; } } }
StripCRLF( pConnectInfo->pszConnectResponse );
if ( pConnectInfo->dwConnectResponseSize > 0 ) { dwRetCode = RasAuthAttributeInsert( dwIndex++, pAttributes, raatConnectInfo, FALSE, strlen( pConnectInfo->pszConnectResponse), (LPVOID)pConnectInfo->pszConnectResponse);
if ( dwRetCode != NO_ERROR ) { break; } } } } }
pAttributes[dwIndex].raaType = raatMinimum; pAttributes[dwIndex].dwLength = 0; pAttributes[dwIndex].Value = NULL;
} while( FALSE );
if ( pConnectInfo != NULL ) { LOCAL_FREE( pConnectInfo ); }
if ( dwRetCode != NO_ERROR ) { RasAuthAttributeDestroy( pAttributes );
return( NULL ); }
return( pAttributes ); }
//**
//
// Call: MakeStopOrInterimAccountingCall
//
// Returns: NO_ERROR - Success
// Non-zero returns - Failure
//
// Description:
//
VOID MakeStopOrInterimAccountingCall( IN PCB * pPcb, IN BOOL fInterimAccounting ) { ULARGE_INTEGER qwCurrentTime; ULARGE_INTEGER qwUpTime; DWORD dwRemainder; DWORD dwActiveTimeInSeconds; DWORD dwRetCode; BYTE buffer[sizeof(RAS_STATISTICS) + (MAX_STATISTICS * sizeof (ULONG))]; RAS_STATISTICS * pStats = (RAS_STATISTICS *)buffer; DWORD dwSize = sizeof (buffer); DWORD dwIndex; RAS_AUTH_ATTRIBUTE * pAttribute; RAS_AUTH_ATTRIBUTE * pAccountingAttributes; LCPCB * pLcpCb = (LCPCB*)(pPcb->LcpCb.pWorkBuf); PSTOP_ACCOUNTING_CONTEXT pStopAcctContext = NULL;
if ( !pLcpCb ) { return; } if ( pLcpCb->Local.Work.AP == 0 ) { //
// If the remote side was not authenticated then do not send an
// accounting request as per RADIUS accounting RFC 2139 sec 5.6.
//
RasAuthAttributeDestroy( pPcb->pAccountingAttributes );
pPcb->pAccountingAttributes = NULL;
return; }
if ( fInterimAccounting ) { if ( PppConfigInfo.RasAcctProviderInterimAccounting == NULL ) { RasAuthAttributeDestroy( pPcb->pAccountingAttributes );
pPcb->pAccountingAttributes = NULL;
return; } } else { if ( PppConfigInfo.RasAcctProviderStopAccounting == NULL ) { RasAuthAttributeDestroy( pPcb->pAccountingAttributes );
pPcb->pAccountingAttributes = NULL;
return; } }
//
// If we have not sent an interim accouting packet then we need to
// create attributes
//
if ( !( pPcb->fFlags & PCBFLAG_INTERIM_ACCT_SENT ) ) { //
// Find out where the array is terminated and then insert attributes
//
for ( dwIndex = 0; pPcb->pAccountingAttributes[dwIndex].raaType != raatMinimum; dwIndex++ );
//
// Undo the NULL termination
//
pPcb->pAccountingAttributes[dwIndex].raaType = raatReserved; pPcb->pAccountingAttributes[dwIndex].dwLength = 0; pPcb->pAccountingAttributes[dwIndex].Value = NULL;
do { //
// Insert session time
//
GetSystemTimeAsFileTime( (FILETIME*)&qwCurrentTime );
if ( ( qwCurrentTime.QuadPart > pPcb->qwActiveTime.QuadPart ) && ( pPcb->qwActiveTime.QuadPart > 0 ) ) { qwUpTime.QuadPart = qwCurrentTime.QuadPart - pPcb->qwActiveTime.QuadPart;
dwActiveTimeInSeconds = RtlEnlargedUnsignedDivide( qwUpTime,(DWORD)10000000,&dwRemainder);
dwRetCode = RasAuthAttributeInsert( dwIndex++, pPcb->pAccountingAttributes, raatAcctSessionTime, FALSE, 4, (PVOID)ULongToPtr(dwActiveTimeInSeconds) );
if ( dwRetCode != NO_ERROR ) { break; } }
//
// Insert Input and Output bytes and packets
//
dwRetCode = RasPortGetStatisticsEx( NULL, pPcb->hPort, (PBYTE)pStats, &dwSize);
if ( dwRetCode == NO_ERROR ) { dwRetCode = RasAuthAttributeInsert( dwIndex++, pPcb->pAccountingAttributes, raatAcctOutputOctets, FALSE, 4, (PVOID)ULongToPtr(pStats->S_Statistics[BYTES_XMITED]));
if ( dwRetCode != NO_ERROR ) { break; }
dwRetCode = RasAuthAttributeInsert( dwIndex++, pPcb->pAccountingAttributes, raatAcctInputOctets, FALSE, 4, (PVOID)ULongToPtr(pStats->S_Statistics[BYTES_RCVED]));
if ( dwRetCode != NO_ERROR ) { break; }
dwRetCode = RasAuthAttributeInsert( dwIndex++, pPcb->pAccountingAttributes, raatAcctOutputPackets, FALSE, 4, (PVOID)ULongToPtr(pStats->S_Statistics[FRAMES_XMITED]));
if ( dwRetCode != NO_ERROR ) { break; } dwRetCode = RasAuthAttributeInsert( dwIndex++, pPcb->pAccountingAttributes, raatAcctInputPackets, FALSE, 4, (PVOID)ULongToPtr(pStats->S_Statistics[FRAMES_RCVED]));
if ( dwRetCode != NO_ERROR ) { break; } }
} while (FALSE);
if ( dwRetCode != NO_ERROR ) { RasAuthAttributeDestroy( pPcb->pAccountingAttributes );
pPcb->pAccountingAttributes = NULL;
return; } //
// Null terminate the array
//
pPcb->pAccountingAttributes[dwIndex].raaType = raatMinimum; pPcb->pAccountingAttributes[dwIndex].dwLength = 0; pPcb->pAccountingAttributes[dwIndex].Value = NULL;
pPcb->fFlags |= PCBFLAG_INTERIM_ACCT_SENT; } else { //
// Else we need to update session time and other attributes
//
GetSystemTimeAsFileTime( (FILETIME*)&qwCurrentTime );
if ( ( qwCurrentTime.QuadPart > pPcb->qwActiveTime.QuadPart ) && ( pPcb->qwActiveTime.QuadPart > 0 ) ) { qwUpTime.QuadPart = qwCurrentTime.QuadPart - pPcb->qwActiveTime.QuadPart;
dwActiveTimeInSeconds = RtlEnlargedUnsignedDivide( qwUpTime,(DWORD)10000000,&dwRemainder);
pAttribute = RasAuthAttributeGet( raatAcctSessionTime, pPcb->pAccountingAttributes );
if ( pAttribute != NULL ) { pAttribute->Value = (PVOID)ULongToPtr(dwActiveTimeInSeconds); } }
//
// Update Input and Output bytes and packets
//
dwRetCode = RasPortGetStatisticsEx( NULL, pPcb->hPort, (PBYTE)pStats, &dwSize);
if ( dwRetCode == NO_ERROR ) { pAttribute = RasAuthAttributeGet( raatAcctOutputOctets, pPcb->pAccountingAttributes );
if ( pAttribute != NULL ) { pAttribute->Value = (PVOID)(ULongToPtr(pStats->S_Statistics[BYTES_XMITED])); }
pAttribute = RasAuthAttributeGet( raatAcctInputOctets, pPcb->pAccountingAttributes );
if ( pAttribute != NULL ) { pAttribute->Value = (PVOID)(ULongToPtr(pStats->S_Statistics[BYTES_RCVED])); }
pAttribute = RasAuthAttributeGet( raatAcctOutputPackets, pPcb->pAccountingAttributes );
if ( pAttribute != NULL ) { pAttribute->Value = (PVOID)(ULongToPtr(pStats->S_Statistics[FRAMES_XMITED])); }
pAttribute = RasAuthAttributeGet( raatAcctInputPackets, pPcb->pAccountingAttributes );
if ( pAttribute != NULL ) { pAttribute->Value = (PVOID)(ULongToPtr(pStats->S_Statistics[FRAMES_RCVED])); } } }
pAttribute = RasAuthAttributeGet( raatAcctLinkCount, pPcb->pAccountingAttributes );
if ( pAttribute != NULL ) { pAttribute->Value = (LPVOID)(ULongToPtr(pPcb->pBcb->dwAcctLinkCount)); }
pAttribute = RasAuthAttributeGet( raatAcctEventTimeStamp, pPcb->pAccountingAttributes );
//
// Insert event timestamp attribute
//
if ( pAttribute != NULL ) { pAttribute->Value = (LPVOID)ULongToPtr(GetSecondsSince1970()); }
if ( !fInterimAccounting ) { DWORD dwTerminateCause = 9;
//
// If this is a stop accounting call, then find out where the
// array is terminated and then insert stop accounting attributes
//
for ( dwIndex = 0; pPcb->pAccountingAttributes[dwIndex].raaType != raatMinimum; dwIndex++ );
//
// Undo the NULL termination
//
pPcb->pAccountingAttributes[dwIndex].raaType = raatReserved; pPcb->pAccountingAttributes[dwIndex].dwLength = 0; pPcb->pAccountingAttributes[dwIndex].Value = NULL;
//
// Insert termination cause attribute
//
if ( pPcb->LcpCb.dwError == ERROR_IDLE_DISCONNECTED ) { dwTerminateCause = TERMINATE_CAUSE_IDLE_TIMEOUT; } else if ( pPcb->LcpCb.dwError == ERROR_PPP_SESSION_TIMEOUT ) { if(pPcb->fFlags & PCBFLAG_QUARANTINE_TIMEOUT) { dwTerminateCause = TERMINATE_CAUSE_USER_ERROR; } else { dwTerminateCause = TERMINATE_CAUSE_SESSION_TIMEOUT; } } else if ( pPcb->fFlags & PCBFLAG_SERVICE_UNAVAILABLE ) { dwTerminateCause = TERMINATE_CAUSE_SERVICE_UNAVAILABLE; } else if ( pPcb->fFlags & PCBFLAG_DOING_CALLBACK ) { dwTerminateCause = TERMINATE_CAUSE_CALLBACK; } else { RASMAN_INFO RasmanInfo;
if ( RasGetInfo( NULL, pPcb->hPort, &RasmanInfo ) == NO_ERROR ) { switch( RasmanInfo.RI_DisconnectReason ) { case USER_REQUESTED: dwTerminateCause = TERMINATE_CAUSE_ADMIN_RESET; if ( pPcb->fFlags & PCBFLAG_RECVD_TERM_REQ ) { //
// Even though we brought the line down, it was at the
// client's request.
//
dwTerminateCause = TERMINATE_CAUSE_USER_REQUEST; } break;
case REMOTE_DISCONNECTION: dwTerminateCause = TERMINATE_CAUSE_USER_REQUEST; break;
case HARDWARE_FAILURE: dwTerminateCause = TERMINATE_CAUSE_PORT_ERROR; break;
default: break; } } }
dwRetCode = RasAuthAttributeInsert( dwIndex++, pPcb->pAccountingAttributes, raatAcctTerminateCause, FALSE, 4, (LPVOID)ULongToPtr(dwTerminateCause) ); pPcb->pAccountingAttributes[dwIndex].raaType = raatMinimum; pPcb->pAccountingAttributes[dwIndex].dwLength = 0; pPcb->pAccountingAttributes[dwIndex].Value = NULL; }
if ( fInterimAccounting ) { pAccountingAttributes = RasAuthAttributeCopy( pPcb->pAccountingAttributes );
if ( NULL == pAccountingAttributes ) { return; } } else { pStopAcctContext = (PSTOP_ACCOUNTING_CONTEXT) LocalAlloc ( LPTR, sizeof(STOP_ACCOUNTING_CONTEXT)); if ( NULL == pStopAcctContext ) { PppLog( 1, "Failed to allocate memory for Stop Accounting Context" ); return; } pStopAcctContext->pPcb= pPcb; //actually there is no need to pass the accounting attributes separately
//need to revisit once this is done.
pStopAcctContext->pAuthAttributes = pPcb->pAccountingAttributes; pAccountingAttributes = pPcb->pAccountingAttributes; }
REF_PROVIDER(g_AcctProv); RtlQueueWorkItem( fInterimAccounting ? InterimAccounting : StopAccounting, fInterimAccounting ? (PVOID)pAccountingAttributes : (PVOID)pStopAcctContext, WT_EXECUTEDEFAULT ); }
//**
//
// Call: GetClientInterfaceInfo
//
// Returns: NO_ERROR - Success
// Non-zero returns - Failure
//
// Description:
//
PBYTE GetClientInterfaceInfo( IN PCB * pPcb ) { HANDLE hAttribute; PBYTE pClientInterface = NULL; PBYTE pClientInterface2= NULL; DWORD dwCount = 0; DWORD dwRetCode = NO_ERROR; BYTE * pbValue = NULL; MIB_IPFORWARDROW * pStaticRoute = NULL; MIB_IPFORWARDROW * pStaticRouteSaved= NULL; RAS_AUTH_ATTRIBUTE * pStaticRoutes = RasAuthAttributeGetFirst( raatFramedRoute, pPcb->pAuthenticatorAttributes, &hAttribute ); BYTE * pbFilter = NULL;
ASSERT(NULL != pPcb->pBcb);
//
// Get quarantine filters for this connection if they
// are available.
//
pbFilter = RasAuthAttributeGetConcatVendorSpecific( 311, MS_VSA_Quarantine_IP_Filter, pPcb->pAuthenticatorAttributes);
if(NULL == pbFilter) { //
// Get the regular filters for this connection if
// no quarantine filters are specified.
//
pbFilter = RasAuthAttributeGetConcatVendorSpecific( 311, MS_VSA_Filter, //22
pPcb->pAuthenticatorAttributes ); } else { PppLog(2, "Found Quarantine-filter"); } if ( ( pStaticRoutes == NULL ) && ( pbFilter == NULL ) ) { return( NULL ); }
if ( pbFilter != NULL ) { dwRetCode = MprInfoDuplicate( pbFilter, &pClientInterface );
LocalFree( pbFilter ); pbFilter = NULL;
if ( dwRetCode != NO_ERROR ) { return( NULL ); } }
if ( pStaticRoutes != NULL ) { if ( pClientInterface == NULL ) { //
// Allocate header
//
dwRetCode = MprInfoCreate(RTR_INFO_BLOCK_VERSION,&pClientInterface);
if ( dwRetCode != NO_ERROR ) { PppLog( 1, "Failed to allocate memory for static routes" );
return( NULL ); } }
//
// Find out how many routes there are
//
for ( dwCount = 0; pStaticRoutes != NULL; dwCount++ ) { pStaticRoutes=RasAuthAttributeGetNext(&hAttribute, raatFramedRoute); }
pStaticRoute = (MIB_IPFORWARDROW*) LOCAL_ALLOC( LPTR, dwCount * sizeof( MIB_IPFORWARDROW ) );
pStaticRouteSaved = pStaticRoute;
if ( pStaticRoute == NULL ) { PppLog( 1, "Failed to allocate memory for static routes" );
MprInfoDelete( pClientInterface );
return( NULL ); }
for ( pbValue = NULL, pStaticRoutes = RasAuthAttributeGetFirst( raatFramedRoute, pPcb->pAuthenticatorAttributes, &hAttribute );
pStaticRoutes != NULL;
pStaticRoute++, pStaticRoutes = RasAuthAttributeGetNext( &hAttribute, raatFramedRoute ) ) { CHAR * pChar; DWORD dwUniqueDigits = 0; DWORD dwMask = 0; DWORD dwIndex;
LocalFree( pbValue );
pbValue = LocalAlloc( LPTR, pStaticRoutes->dwLength + 1 );
if ( NULL == pbValue ) { PppLog( 1, "Failed to allocate memory for static routes" );
continue; }
CopyMemory( pbValue, (BYTE *)(pStaticRoutes->Value), pStaticRoutes->dwLength );
pChar = strtok( (CHAR *) pbValue, "/" );
if ( pChar != NULL ) { pStaticRoute->dwForwardDest = inet_addr( pChar );
if ( pStaticRoute->dwForwardDest == INADDR_NONE ) { PppLog(1, "Ignoring invalid static route - no destination IP");
continue; }
pChar = strtok( NULL, " " );
if ( pChar == NULL ) { PppLog( 1, "Ignoring invalid static route - no MASK");
continue; }
dwUniqueDigits = atoi( pChar );
if ( dwUniqueDigits > 32 ) { PppLog( 1, "Ignoring invalid static route - invalid MASK");
continue; }
for ( dwIndex = 0; dwIndex < dwUniqueDigits; dwIndex++ ) { dwMask |= ( 0x80000000 >> dwIndex ); }
HostToWireFormat32( dwMask, (PBYTE)&(pStaticRoute->dwForwardMask)); } else { pChar = strtok( (CHAR *) pbValue, " " );
if ( pChar == NULL ) { PppLog(1, "Ignoring invalid static route - no destination IP");
continue; } else { pStaticRoute->dwForwardDest = inet_addr( pChar ); pStaticRoute->dwForwardMask = GetClassMask( pStaticRoute->dwForwardDest ); } }
pChar = strtok( NULL, " " );
if ( pChar == NULL ) { PppLog( 1, "Ignoring invalid static route - no next hop IP");
continue; }
pStaticRoute->dwForwardNextHop = inet_addr( pChar );
if ( pStaticRoute->dwForwardDest == INADDR_NONE ) { PppLog(1,"Ignoring invalid static route - invalid nexthop IP");
continue; }
pChar = strtok( NULL, " " );
if ( pChar != NULL ) { pStaticRoute->dwForwardMetric1 = atoi( pChar ); }
pChar = strtok( NULL, " " );
if ( pChar != NULL ) { pStaticRoute->dwForwardMetric2 = atoi( pChar ); }
pChar = strtok( NULL, " " );
if ( pChar != NULL ) { pStaticRoute->dwForwardMetric3 = atoi( pChar ); }
pChar = strtok( NULL, " " );
if ( pChar != NULL ) { pStaticRoute->dwForwardMetric4 = atoi( pChar ); }
pChar = strtok( NULL, " " );
if ( pChar != NULL ) { pStaticRoute->dwForwardMetric5 = atoi( pChar ); } }
LocalFree( pbValue );
dwRetCode = MprInfoBlockAdd( pClientInterface, IP_ROUTE_INFO, sizeof( MIB_IPFORWARDROW ), dwCount, (PBYTE)pStaticRouteSaved, &pClientInterface2 );
MprInfoDelete( pClientInterface );
if ( dwRetCode != NO_ERROR ) { PppLog( 1, "MprInfoBlockAdd failed and returned %d", dwRetCode );
LOCAL_FREE( pStaticRouteSaved );
return( NULL ); } else { pClientInterface = pClientInterface2; }
LOCAL_FREE( pStaticRouteSaved ); }
return( pClientInterface ); }
//**
//
// Call: LoadParserDll
//
// Returns: VOID
//
// Description: Loads the parser DLL with the entry points PacketFromPeer,
// PacketToPeer, and PacketFree.
//
VOID LoadParserDll( IN HKEY hKeyPpp ) { LONG lRet; DWORD dwType; DWORD dwSize; CHAR* pszPath = NULL; CHAR* pszExpandedPath = NULL; HINSTANCE hInstance = NULL; FARPROC pPacketFromPeer; FARPROC pPacketToPeer; FARPROC pPacketFree; BOOL fUnloadDLL = TRUE;
//
// Find how big the path is
//
dwSize = 0; lRet = RegQueryValueExA( hKeyPpp, RAS_VALUENAME_PARSEDLLPATH, NULL, &dwType, NULL, &dwSize );
if (ERROR_SUCCESS != lRet) { goto LDone; }
if ( (REG_EXPAND_SZ != dwType) && (REG_SZ != dwType)) { goto LDone; }
pszPath = LOCAL_ALLOC(LPTR, dwSize);
if (NULL == pszPath) { goto LDone; }
//
// Read the path
//
lRet = RegQueryValueExA( hKeyPpp, RAS_VALUENAME_PARSEDLLPATH, NULL, &dwType, pszPath, &dwSize );
if (ERROR_SUCCESS != lRet) { goto LDone; }
//
// Replace the %SystemRoot% with the actual path.
//
dwSize = ExpandEnvironmentStringsA(pszPath, NULL, 0);
if (0 == dwSize) { goto LDone; }
pszExpandedPath = LOCAL_ALLOC(LPTR, dwSize);
if (NULL == pszExpandedPath) { goto LDone; }
dwSize = ExpandEnvironmentStringsA( pszPath, pszExpandedPath, dwSize ); if (0 == dwSize) { goto LDone; }
if ( (NULL != PppConfigInfo.pszParserDllPath) && (!strcmp(pszExpandedPath, PppConfigInfo.pszParserDllPath))) { //
// The DLL is already loaded
//
fUnloadDLL = FALSE; goto LDone; }
hInstance = LoadLibraryA(pszExpandedPath);
if (NULL == hInstance) { goto LDone; }
fUnloadDLL = FALSE;
pPacketFromPeer = GetProcAddress(hInstance, "PacketFromPeer"); pPacketToPeer = GetProcAddress(hInstance, "PacketToPeer"); pPacketFree = GetProcAddress(hInstance, "PacketFree");
FreeLibrary(PppConfigInfo.hInstanceParserDll); PppConfigInfo.hInstanceParserDll = hInstance; hInstance = NULL;
if (NULL != PppConfigInfo.pszParserDllPath) { LOCAL_FREE(PppConfigInfo.pszParserDllPath); } PppConfigInfo.pszParserDllPath = pszExpandedPath; pszExpandedPath = NULL;
PppConfigInfo.PacketFromPeer = (VOID(*)(HANDLE, BYTE*, DWORD, BYTE**, DWORD*)) pPacketFromPeer; PppConfigInfo.PacketToPeer = (VOID(*)(HANDLE, BYTE*, DWORD, BYTE**, DWORD*)) pPacketToPeer; PppConfigInfo.PacketFree = (VOID(*)(BYTE*)) pPacketFree;
LDone:
if (NULL != pszPath) { LOCAL_FREE(pszPath); }
if (NULL != pszExpandedPath) { LOCAL_FREE(pszExpandedPath); }
if (NULL != hInstance) { FreeLibrary(hInstance); }
if (fUnloadDLL) { FreeLibrary(PppConfigInfo.hInstanceParserDll); PppConfigInfo.hInstanceParserDll = NULL;
if (NULL != PppConfigInfo.pszParserDllPath) { LOCAL_FREE(PppConfigInfo.pszParserDllPath); } PppConfigInfo.pszParserDllPath = NULL;
PppConfigInfo.PacketFromPeer = NULL; PppConfigInfo.PacketToPeer = NULL; PppConfigInfo.PacketFree = NULL; } }
//**
//
// Call: PortSendOrDisconnect
//
// Returns: NO_ERROR - Success
// Non-zero returns - Failure
//
// Description:
//
DWORD PortSendOrDisconnect( IN PCB * pPcb, IN DWORD cbPacket ) { DWORD dwRetCode; BYTE* pData = NULL; DWORD dwSize = 0; BOOL fBufferReceivedFromParser = FALSE;
if ( NULL != PppConfigInfo.PacketToPeer ) { PppConfigInfo.PacketToPeer( pPcb->hPort, (BYTE*)(pPcb->pSendBuf), cbPacket, &pData, &dwSize ); }
if ( NULL == pData ) { pData = (BYTE*)(pPcb->pSendBuf); dwSize = cbPacket; } else { fBufferReceivedFromParser = TRUE; }
dwRetCode = RasPortSend( pPcb->hPort, pData, dwSize );
if ( NO_ERROR != dwRetCode ) { PppLog( 1, "RasPortSend on port %d failed: %d", pPcb->hPort, dwRetCode );
pPcb->LcpCb.dwError = dwRetCode;
pPcb->fFlags |= PCBFLAG_STOPPED_MSG_SENT;
NotifyCaller( pPcb, ( pPcb->fFlags & PCBFLAG_IS_SERVER ) ? PPPDDMMSG_Stopped : PPPMSG_Stopped, &(pPcb->LcpCb.dwError) ); }
if ( fBufferReceivedFromParser ) { PPP_ASSERT( NULL != PppConfigInfo.PacketFree ); PppConfigInfo.PacketFree( pData ); }
return( dwRetCode ); }
//**
//
// Call: ReceiveViaParser
//
// Returns: VOID
//
// Description:
//
VOID ReceiveViaParser( IN PCB * pPcb, IN PPP_PACKET * pPacket, IN DWORD dwPacketLength ) { BYTE* pData = NULL; DWORD dwSize = 0; BOOL fBufferReceivedFromParser = FALSE;
if ( NULL != PppConfigInfo.PacketFromPeer ) { PppConfigInfo.PacketFromPeer( pPcb->hPort, (BYTE*)pPacket, dwPacketLength, &pData, &dwSize ); }
if ( NULL == pData ) { pData = (BYTE*)pPacket; dwSize = dwPacketLength; } else { fBufferReceivedFromParser = TRUE; }
FsmReceive( pPcb, (PPP_PACKET*) pData, dwSize );
if ( fBufferReceivedFromParser ) { PPP_ASSERT( NULL != PppConfigInfo.PacketFree ); PppConfigInfo.PacketFree( pData ); } }
//**
//
// Call: GetSecondsSince1970
//
// Returns: NO_ERROR - Success
// Non-zero returns - Failure
//
// Description:
//
DWORD GetSecondsSince1970( VOID ) { SYSTEMTIME LocalTime; TIME_FIELDS LocalTimeFields; LARGE_INTEGER TempTime; LARGE_INTEGER SystemTime; DWORD RetTime;
GetLocalTime( &LocalTime );
LocalTimeFields.Year = LocalTime.wYear; LocalTimeFields.Month = LocalTime.wMonth; LocalTimeFields.Day = LocalTime.wDay; LocalTimeFields.Hour = LocalTime.wHour; LocalTimeFields.Minute = LocalTime.wMinute; LocalTimeFields.Second = LocalTime.wSecond; LocalTimeFields.Milliseconds = LocalTime.wMilliseconds; LocalTimeFields.Weekday = LocalTime.wDayOfWeek;
RtlTimeFieldsToTime(&LocalTimeFields, &TempTime);
RtlLocalTimeToSystemTime(&TempTime, &SystemTime);
RtlTimeToSecondsSince1970(&SystemTime, &RetTime);
return( RetTime ); }
//**
//
// Call: IsPschedRunning
//
// Returns: TRUE iff Psched is running
//
// Description:
//
BOOL IsPschedRunning( VOID ) { SC_HANDLE hCont = NULL; SC_HANDLE hSched = NULL; DWORD dwErr = NO_ERROR; SERVICE_STATUS Status; BOOL fRet = FALSE;
//
// Initialize
//
ZeroMemory( &Status, sizeof(Status) ); do { hCont = OpenSCManager( NULL, NULL, GENERIC_READ );
if ( hCont == NULL ) { dwErr = GetLastError(); PppLog( 1, "OpenSCManager failed: %d", dwErr ); break; }
hSched = OpenService( hCont, TEXT("psched"), SERVICE_QUERY_STATUS );
if ( hSched == NULL ) { dwErr = GetLastError(); PppLog( 1, "OpenService failed: %d", dwErr ); break; }
if ( !QueryServiceStatus( hSched, &Status )) { dwErr = GetLastError(); PppLog( 1, "QueryServiceStatus failed: %d", dwErr ); break; } fRet = ( Status.dwCurrentState == SERVICE_RUNNING ); } while ( FALSE );
//
// Cleanup
//
if ( hSched ) { CloseServiceHandle( hSched ); } if ( hCont ) { CloseServiceHandle( hCont ); }
return( fRet ); }
//**
//
// Call: LogPPPPacket
//
// Returns: None
//
// Description:
//
VOID LogPPPPacket( IN BOOL fReceived, IN PCB * pPcb, IN PPP_PACKET * pPacket, IN DWORD cbPacket ) { SYSTEMTIME SystemTime; CHAR * pchProtocol; CHAR * pchType; BYTE Id = 0; BYTE bCode; DWORD cbTracePacketSize = cbPacket; DWORD dwUnknownPacketTraceSize; BOOL fPrint = TRUE;
dwUnknownPacketTraceSize = PppConfigInfo.dwUnknownPacketTraceSize;
GetSystemTime( &SystemTime );
if ( cbPacket > PPP_CONFIG_HDR_LEN ) { bCode = *(((CHAR*)pPacket)+PPP_PACKET_HDR_LEN);
if ( ( bCode == 0 ) || ( bCode > TIME_REMAINING ) ) { pchType = "UNKNOWN"; } else { pchType = FsmCodes[ bCode ]; }
Id = *(((CHAR*)pPacket)+PPP_PACKET_HDR_LEN+1); } else { pchType = "UNKNOWN"; }
if ( cbPacket > PPP_PACKET_HDR_LEN ) { switch( WireToHostFormat16( (CHAR*)pPacket ) ) { case PPP_LCP_PROTOCOL: pchProtocol = "LCP"; break; case PPP_BACP_PROTOCOL: pchProtocol = "BACP"; break; case PPP_BAP_PROTOCOL: pchProtocol = "BAP"; pchType = "Protocol specific"; break; case PPP_PAP_PROTOCOL: pchProtocol = "PAP"; pchType = "Protocol specific"; fPrint = FALSE; break; case PPP_CBCP_PROTOCOL: pchProtocol = "CBCP"; pchType = "Protocol specific"; break; case PPP_CHAP_PROTOCOL: pchProtocol = "CHAP"; pchType = "Protocol specific"; break; case PPP_IPCP_PROTOCOL: pchProtocol = "IPCP"; break; case PPP_ATCP_PROTOCOL: pchProtocol = "ATCP"; break; case PPP_IPXCP_PROTOCOL: pchProtocol = "IPXCP"; break; case PPP_NBFCP_PROTOCOL: pchProtocol = "NBFCP"; break; case PPP_CCP_PROTOCOL: pchProtocol = "CCP"; break; case PPP_EAP_PROTOCOL: pchProtocol = "EAP"; pchType = "Protocol specific"; if ( cbTracePacketSize > dwUnknownPacketTraceSize ) { cbTracePacketSize = dwUnknownPacketTraceSize; } break; case PPP_SPAP_NEW_PROTOCOL: pchProtocol = "SHIVA PAP"; pchType = "Protocol specific"; break; default: pchProtocol = "UNKNOWN"; if ( cbTracePacketSize > dwUnknownPacketTraceSize ) { cbTracePacketSize = dwUnknownPacketTraceSize; } break; } } else { pchProtocol = "UNKNOWN"; }
PppLog( 1, "%sPPP packet %s at %0*d/%0*d/%0*d %0*d:%0*d:%0*d:%0*d", fReceived ? ">" : "<", fReceived ? "received" : "sent", 2, SystemTime.wMonth, 2, SystemTime.wDay, 2, SystemTime.wYear, 2, SystemTime.wHour, 2, SystemTime.wMinute, 2, SystemTime.wSecond, 3, SystemTime.wMilliseconds ); PppLog(1, "%sProtocol = %s, Type = %s, Length = 0x%x, Id = 0x%x, Port = %d", fReceived ? ">" : "<", pchProtocol, pchType, cbPacket, Id, pPcb->hPort );
if ( fPrint ) { TraceDumpExA( PppConfigInfo.dwTraceId, TRACE_LEVEL_1 | TRACE_USE_MSEC, (CHAR*)pPacket, cbTracePacketSize, 1, FALSE, fReceived ? ">" : "<" ); }
PppLog(1," " ); }
//**
//
// Call: PppLog
//
// Returns: None
//
// Description: Will print to the PPP logfile
//
VOID PppLog( IN DWORD DbgLevel, ... ) { va_list arglist; CHAR *Format; char OutputBuffer[1024];
va_start( arglist, DbgLevel );
Format = va_arg( arglist, CHAR* );
vsprintf( OutputBuffer, Format, arglist );
va_end( arglist );
TracePutsExA( PppConfigInfo.dwTraceId, (( DbgLevel == 1 ) ? TRACE_LEVEL_1 : TRACE_LEVEL_2 ) | TRACE_USE_MSEC | TRACE_USE_DATE, OutputBuffer ); }
#ifdef MEM_LEAK_CHECK
LPVOID DebugAlloc( DWORD Flags, DWORD dwSize ) { DWORD Index; LPBYTE pMem = (LPBYTE)HeapAlloc( PppConfigInfo.hHeap, HEAP_ZERO_MEMORY,dwSize+8);
if ( pMem == NULL ) return( pMem );
for( Index=0; Index < PPP_MEM_TABLE_SIZE; Index++ ) { if ( PppMemTable[Index] == NULL ) { PppMemTable[Index] = pMem; break; } }
PPP_ASSERT( Index != PPP_MEM_TABLE_SIZE );
return( (LPVOID)pMem ); }
BOOL DebugFree( PVOID pMem ) { DWORD Index;
for( Index=0; Index < PPP_MEM_TABLE_SIZE; Index++ ) { if ( PppMemTable[Index] == pMem ) { PppMemTable[Index] = NULL; break; } }
ASSERT( Index != PPP_MEM_TABLE_SIZE );
return( HeapFree( PppConfigInfo.hHeap, 0, pMem ) ); }
LPVOID DebugReAlloc( PVOID pMem, DWORD dwSize ) { DWORD Index;
if ( pMem == NULL ) { PPP_ASSERT(FALSE); }
for( Index=0; Index < PPP_MEM_TABLE_SIZE; Index++ ) { if ( PppMemTable[Index] == pMem ) { PppMemTable[Index] = HeapReAlloc( PppConfigInfo.hHeap, HEAP_ZERO_MEMORY, pMem, dwSize );
pMem = PppMemTable[Index];
break; } }
PPP_ASSERT( Index != PPP_MEM_TABLE_SIZE );
return( (LPVOID)pMem ); }
#endif
|