1020 lines
26 KiB
C
1020 lines
26 KiB
C
|
/*******************************************************************/
|
|||
|
/* Copyright(c) 1995 Microsoft Corporation */
|
|||
|
/*******************************************************************/
|
|||
|
|
|||
|
//***
|
|||
|
//
|
|||
|
// Filename: rmhand.c
|
|||
|
//
|
|||
|
// Description: This module contains the procedures for the
|
|||
|
// DDM's procedure-driven state machine
|
|||
|
// that handles RasMan events.
|
|||
|
//
|
|||
|
// NOTE:Rasman should be modified to set a flag when a frame is
|
|||
|
// received or and state change has occurred. This will save
|
|||
|
// DDM from getting info for all the ports.
|
|||
|
//
|
|||
|
// Author: Stefan Solomon (stefans) May 26, 1992.
|
|||
|
//
|
|||
|
//***
|
|||
|
#include "ddm.h"
|
|||
|
#include "timer.h"
|
|||
|
#include "handlers.h"
|
|||
|
#include "objects.h"
|
|||
|
#include "util.h"
|
|||
|
#include "routerif.h"
|
|||
|
#include <raserror.h>
|
|||
|
#include <rasppp.h>
|
|||
|
#include <ddmif.h>
|
|||
|
#include <serial.h>
|
|||
|
#include "rasmanif.h"
|
|||
|
#include <ras.h>
|
|||
|
#include <string.h>
|
|||
|
#include <stdlib.h>
|
|||
|
#include <memory.h>
|
|||
|
|
|||
|
//***
|
|||
|
//
|
|||
|
// Function: SvDevConnected
|
|||
|
//
|
|||
|
// Description: Handles the device transition to connected state
|
|||
|
//
|
|||
|
//***
|
|||
|
VOID
|
|||
|
SvDevConnected(
|
|||
|
IN PDEVICE_OBJECT pDeviceObj
|
|||
|
)
|
|||
|
{
|
|||
|
PCONNECTION_OBJECT pConnObj;
|
|||
|
HCONN hConnection;
|
|||
|
DWORD dwRetCode;
|
|||
|
LPWSTR auditstrp[3];
|
|||
|
|
|||
|
DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM,
|
|||
|
"SvDevConnected: Entered, hPort=%d", pDeviceObj->hPort);
|
|||
|
|
|||
|
//
|
|||
|
// Get handle to the connection or bundle for this link
|
|||
|
//
|
|||
|
|
|||
|
if ( RasPortGetBundle( NULL,
|
|||
|
pDeviceObj->hPort,
|
|||
|
&hConnection ) != NO_ERROR )
|
|||
|
{
|
|||
|
DevStartClosing(pDeviceObj);
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
switch (pDeviceObj->DeviceState)
|
|||
|
{
|
|||
|
case DEV_OBJ_LISTEN_COMPLETE:
|
|||
|
|
|||
|
pDeviceObj->hConnection = hConnection;
|
|||
|
|
|||
|
//
|
|||
|
// reset the H/W Error signal state
|
|||
|
//
|
|||
|
|
|||
|
pDeviceObj->dwHwErrorSignalCount = HW_FAILURE_CNT;
|
|||
|
|
|||
|
//
|
|||
|
// get the system time for this connection
|
|||
|
//
|
|||
|
|
|||
|
GetLocalTime( &pDeviceObj->ConnectionTime );
|
|||
|
|
|||
|
//
|
|||
|
// get the frame broadcasted by the client
|
|||
|
//
|
|||
|
|
|||
|
if ( ( dwRetCode = RmReceiveFrame( pDeviceObj ) ) != NO_ERROR )
|
|||
|
{
|
|||
|
//
|
|||
|
// can't get the broadcast frame. This is a fatal error
|
|||
|
// Log the error
|
|||
|
//
|
|||
|
|
|||
|
auditstrp[0] = pDeviceObj->wchPortName;
|
|||
|
|
|||
|
DDMLogErrorString( ROUTERLOG_CANT_RECEIVE_FRAME, 1, auditstrp,
|
|||
|
dwRetCode, 1);
|
|||
|
|
|||
|
DevStartClosing( pDeviceObj );
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
//
|
|||
|
// switch to frame receiving state
|
|||
|
//
|
|||
|
|
|||
|
pDeviceObj->DeviceState = DEV_OBJ_RECEIVING_FRAME;
|
|||
|
|
|||
|
if ( RAS_DEVICE_TYPE( pDeviceObj->dwDeviceType ) != RDT_Atm )
|
|||
|
{
|
|||
|
//
|
|||
|
// start authentication timer
|
|||
|
//
|
|||
|
|
|||
|
TimerQRemove( (HANDLE)pDeviceObj->hPort, SvAuthTimeout );
|
|||
|
|
|||
|
TimerQInsert( (HANDLE)pDeviceObj->hPort,
|
|||
|
gblDDMConfigInfo.dwAuthenticateTime,
|
|||
|
SvAuthTimeout );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
case DEV_OBJ_CALLBACK_CONNECTING:
|
|||
|
|
|||
|
{
|
|||
|
|
|||
|
//
|
|||
|
// log on the client disconnection
|
|||
|
//
|
|||
|
|
|||
|
WCHAR wchFullUserName[UNLEN+DNLEN+2];
|
|||
|
|
|||
|
if ( pDeviceObj->wchDomainName[0] != TEXT('\0') )
|
|||
|
{
|
|||
|
wcscpy( wchFullUserName, pDeviceObj->wchDomainName );
|
|||
|
wcscat( wchFullUserName, TEXT("\\") );
|
|||
|
wcscat( wchFullUserName, pDeviceObj->wchUserName );
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
wcscpy( wchFullUserName, pDeviceObj->wchUserName );
|
|||
|
}
|
|||
|
|
|||
|
auditstrp[0] = wchFullUserName;
|
|||
|
auditstrp[1] = pDeviceObj->wchPortName;
|
|||
|
auditstrp[2] = pDeviceObj->wchCallbackNumber;
|
|||
|
|
|||
|
DDMLogInformation( ROUTERLOG_CLIENT_CALLED_BACK, 3, auditstrp);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// set up the new state
|
|||
|
//
|
|||
|
|
|||
|
pDeviceObj->DeviceState = DEV_OBJ_AUTH_IS_ACTIVE;
|
|||
|
|
|||
|
//
|
|||
|
// start authentication timer
|
|||
|
//
|
|||
|
|
|||
|
TimerQRemove( (HANDLE)pDeviceObj->hPort, SvAuthTimeout );
|
|||
|
|
|||
|
TimerQInsert( (HANDLE)pDeviceObj->hPort,
|
|||
|
gblDDMConfigInfo.dwAuthenticateTime,
|
|||
|
SvAuthTimeout );
|
|||
|
|
|||
|
//
|
|||
|
// and tell auth to restart conversation
|
|||
|
//
|
|||
|
|
|||
|
if ( pDeviceObj->fFlags & DEV_OBJ_IS_PPP )
|
|||
|
{
|
|||
|
//
|
|||
|
// Need to set framing to PPP to make callback over ISDN
|
|||
|
// work.
|
|||
|
//
|
|||
|
|
|||
|
RAS_FRAMING_INFO RasFramingInfo;
|
|||
|
|
|||
|
ZeroMemory( &RasFramingInfo, sizeof( RasFramingInfo ) );
|
|||
|
|
|||
|
//
|
|||
|
// Default ACCM for PPP is 0xFFFFFFFF
|
|||
|
//
|
|||
|
|
|||
|
RasFramingInfo.RFI_RecvACCM = 0xFFFFFFFF;
|
|||
|
RasFramingInfo.RFI_SendACCM = 0xFFFFFFFF;
|
|||
|
RasFramingInfo.RFI_MaxSendFrameSize = 1500;
|
|||
|
RasFramingInfo.RFI_MaxRecvFrameSize = 1500;
|
|||
|
RasFramingInfo.RFI_SendFramingBits = PPP_FRAMING;
|
|||
|
RasFramingInfo.RFI_RecvFramingBits = PPP_FRAMING;
|
|||
|
|
|||
|
RasPortSetFramingEx( pDeviceObj->hPort, &RasFramingInfo );
|
|||
|
|
|||
|
pDeviceObj->hConnection = hConnection;
|
|||
|
|
|||
|
PppDdmCallbackDone(pDeviceObj->hPort, pDeviceObj->wchCallbackNumber);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
// We only suport PPP framing in the server
|
|||
|
//
|
|||
|
|
|||
|
RTASSERT(FALSE);
|
|||
|
}
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//***
|
|||
|
//
|
|||
|
// Function: SvDevDisconnected
|
|||
|
//
|
|||
|
// Descr: Handles the device transition to disconnected state
|
|||
|
//
|
|||
|
//***
|
|||
|
|
|||
|
VOID
|
|||
|
SvDevDisconnected(
|
|||
|
IN PDEVICE_OBJECT pDeviceObj
|
|||
|
)
|
|||
|
{
|
|||
|
DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM,
|
|||
|
"SvDevDisconnected:Entered, hPort=%d",pDeviceObj->hPort);
|
|||
|
|
|||
|
switch (pDeviceObj->DeviceState)
|
|||
|
{
|
|||
|
case DEV_OBJ_LISTENING:
|
|||
|
|
|||
|
//
|
|||
|
// h/w error; start h/w error timer
|
|||
|
//
|
|||
|
|
|||
|
pDeviceObj->DeviceState = DEV_OBJ_HW_FAILURE;
|
|||
|
|
|||
|
TimerQRemove( (HANDLE)pDeviceObj->hPort, SvHwErrDelayCompleted );
|
|||
|
|
|||
|
TimerQInsert( (HANDLE)pDeviceObj->hPort, HW_FAILURE_WAIT_TIME,
|
|||
|
SvHwErrDelayCompleted );
|
|||
|
|
|||
|
//
|
|||
|
// if hw error has not been signaled for this port,
|
|||
|
// decrement the counter and signal when 0
|
|||
|
//
|
|||
|
|
|||
|
if(pDeviceObj->dwHwErrorSignalCount)
|
|||
|
{
|
|||
|
pDeviceObj->dwHwErrorSignalCount--;
|
|||
|
|
|||
|
if(pDeviceObj->dwHwErrorSignalCount == 0)
|
|||
|
{
|
|||
|
SignalHwError(pDeviceObj);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
case DEV_OBJ_CALLBACK_DISCONNECTING:
|
|||
|
|
|||
|
//
|
|||
|
// disconnection done; can start waiting the callback delay
|
|||
|
//
|
|||
|
|
|||
|
pDeviceObj->DeviceState = DEV_OBJ_CALLBACK_DISCONNECTED;
|
|||
|
|
|||
|
TimerQRemove( (HANDLE)pDeviceObj->hPort, SvCbDelayCompleted );
|
|||
|
|
|||
|
TimerQInsert( (HANDLE)pDeviceObj->hPort, pDeviceObj->dwCallbackDelay,
|
|||
|
SvCbDelayCompleted);
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
case DEV_OBJ_CALLBACK_CONNECTING:
|
|||
|
|
|||
|
if (gblDDMConfigInfo.dwCallbackRetries > pDeviceObj->dwCallbackRetries)
|
|||
|
{
|
|||
|
DDMTRACE( "Callback failed, retrying" );
|
|||
|
|
|||
|
pDeviceObj->dwCallbackRetries++;
|
|||
|
|
|||
|
pDeviceObj->DeviceState = DEV_OBJ_CALLBACK_DISCONNECTED;
|
|||
|
|
|||
|
TimerQRemove( (HANDLE)pDeviceObj->hPort, SvCbDelayCompleted );
|
|||
|
|
|||
|
TimerQInsert( (HANDLE)pDeviceObj->hPort,
|
|||
|
pDeviceObj->dwCallbackDelay,
|
|||
|
SvCbDelayCompleted );
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
case DEV_OBJ_LISTEN_COMPLETE:
|
|||
|
case DEV_OBJ_RECEIVING_FRAME:
|
|||
|
case DEV_OBJ_AUTH_IS_ACTIVE:
|
|||
|
|
|||
|
//
|
|||
|
// accidental disconnection; clean-up and restart on this device
|
|||
|
//
|
|||
|
|
|||
|
DevStartClosing( pDeviceObj );
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
case DEV_OBJ_ACTIVE:
|
|||
|
|
|||
|
DevStartClosing(pDeviceObj);
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
case DEV_OBJ_CLOSING:
|
|||
|
|
|||
|
DevCloseComplete(pDeviceObj);
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
VOID
|
|||
|
SvDevListenComplete(
|
|||
|
IN PDEVICE_OBJECT pDeviceObj
|
|||
|
)
|
|||
|
{
|
|||
|
LPWSTR auditstrp[1];
|
|||
|
DWORD dwLength;
|
|||
|
DWORD dwRetCode;
|
|||
|
DWORD dwBucketIndex = DeviceObjHashPortToBucket( pDeviceObj->hPort );
|
|||
|
|
|||
|
//
|
|||
|
// We reset these values here is case they were set for dialout and the
|
|||
|
// dialout failed, we may have not been able to clean up in
|
|||
|
// the RasConnectCallback routine in rasapiif.c since the
|
|||
|
// RasGetSubEntryHandle may have failed and we hence do not get a
|
|||
|
// pointer to the port so we could not cleanup.
|
|||
|
//
|
|||
|
|
|||
|
pDeviceObj->DeviceState = DEV_OBJ_LISTEN_COMPLETE;
|
|||
|
pDeviceObj->fFlags &= ~DEV_OBJ_OPENED_FOR_DIALOUT;
|
|||
|
pDeviceObj->fFlags &= ~DEV_OBJ_SECURITY_DLL_USED;
|
|||
|
pDeviceObj->hConnection = (HCONN)INVALID_HANDLE_VALUE;
|
|||
|
pDeviceObj->wchUserName[0] = (WCHAR)NULL;
|
|||
|
pDeviceObj->wchDomainName[0] = (WCHAR)NULL;
|
|||
|
pDeviceObj->wchCallbackNumber[0] = (WCHAR)NULL;
|
|||
|
pDeviceObj->hRasConn = (HRASCONN)NULL;
|
|||
|
pDeviceObj->pRasmanSendBuffer = NULL;
|
|||
|
pDeviceObj->pRasmanRecvBuffer = NULL;
|
|||
|
pDeviceObj->dwCallbackRetries = 0;
|
|||
|
|
|||
|
pDeviceObj->dwRecvBufferLen = 1500;
|
|||
|
|
|||
|
dwRetCode = RasGetBuffer((CHAR**)&pDeviceObj->pRasmanRecvBuffer,
|
|||
|
&((pDeviceObj->dwRecvBufferLen)) );
|
|||
|
|
|||
|
if ( dwRetCode != NO_ERROR )
|
|||
|
{
|
|||
|
auditstrp[0] = pDeviceObj->wchPortName;
|
|||
|
|
|||
|
DDMLogErrorString( ROUTERLOG_CANT_RECEIVE_BYTES, 1, auditstrp,
|
|||
|
dwRetCode, 1);
|
|||
|
|
|||
|
DevStartClosing(pDeviceObj);
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// If the security DLL is not loaded or we are not serial, simply
|
|||
|
// change the state
|
|||
|
//
|
|||
|
|
|||
|
if ( ( gblDDMConfigInfo.lpfnRasBeginSecurityDialog == NULL ) ||
|
|||
|
( gblDDMConfigInfo.lpfnRasEndSecurityDialog == NULL ) )
|
|||
|
{
|
|||
|
//
|
|||
|
// Change RASMAN state to CONNECTED from LISTENCOMPLETE and signal
|
|||
|
// RmEventHandler
|
|||
|
//
|
|||
|
|
|||
|
if ( RasPortConnectComplete(pDeviceObj->hPort) != NO_ERROR )
|
|||
|
{
|
|||
|
DevStartClosing(pDeviceObj);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
SetEvent( gblSupervisorEvents[NUM_DDM_EVENTS+dwBucketIndex] );
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
// Otherwise call the security dll ordinal to begin the 3rd party
|
|||
|
// security dialog with the client
|
|||
|
|
|||
|
dwLength = 1500;
|
|||
|
|
|||
|
dwRetCode = RasGetBuffer((CHAR**)&pDeviceObj->pRasmanSendBuffer,
|
|||
|
&dwLength );
|
|||
|
|
|||
|
if ( dwRetCode != NO_ERROR )
|
|||
|
{
|
|||
|
auditstrp[0] = pDeviceObj->wchPortName;
|
|||
|
|
|||
|
DDMLogErrorString( ROUTERLOG_CANT_RECEIVE_BYTES, 1, auditstrp,
|
|||
|
dwRetCode, 1);
|
|||
|
|
|||
|
DevStartClosing(pDeviceObj);
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// Make sure that this device type supports raw mode.
|
|||
|
//
|
|||
|
|
|||
|
if ( RasPortSend( pDeviceObj->hPort,
|
|||
|
(CHAR*)pDeviceObj->pRasmanSendBuffer,
|
|||
|
0 ) != NO_ERROR )
|
|||
|
{
|
|||
|
RasFreeBuffer( pDeviceObj->pRasmanSendBuffer );
|
|||
|
|
|||
|
pDeviceObj->pRasmanSendBuffer = NULL;
|
|||
|
|
|||
|
//
|
|||
|
// Change RASMAN state to CONNECTED from LISTENCOMPLETE and signal
|
|||
|
// RmEventHandler
|
|||
|
//
|
|||
|
|
|||
|
if ( RasPortConnectComplete( pDeviceObj->hPort ) != NO_ERROR )
|
|||
|
{
|
|||
|
DevStartClosing(pDeviceObj);
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
SetEvent( gblSupervisorEvents[NUM_DDM_EVENTS+dwBucketIndex] );
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
dwRetCode = (*gblDDMConfigInfo.lpfnRasBeginSecurityDialog)(
|
|||
|
pDeviceObj->hPort,
|
|||
|
pDeviceObj->pRasmanSendBuffer ,
|
|||
|
dwLength,
|
|||
|
pDeviceObj->pRasmanRecvBuffer,
|
|||
|
pDeviceObj->dwRecvBufferLen,
|
|||
|
RasSecurityDialogComplete );
|
|||
|
|
|||
|
if ( dwRetCode != NO_ERROR )
|
|||
|
{
|
|||
|
//
|
|||
|
// Audit failure due to error and hangup the line
|
|||
|
//
|
|||
|
|
|||
|
auditstrp[0] = pDeviceObj->wchPortName;
|
|||
|
|
|||
|
DDMLogErrorString( ROUTERLOG_SEC_AUTH_INTERNAL_ERROR,1,auditstrp,
|
|||
|
dwRetCode, 1);
|
|||
|
|
|||
|
DevStartClosing(pDeviceObj);
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
pDeviceObj->SecurityState = DEV_OBJ_SECURITY_DIALOG_ACTIVE;
|
|||
|
|
|||
|
pDeviceObj->fFlags |= DEV_OBJ_SECURITY_DLL_USED;
|
|||
|
|
|||
|
//
|
|||
|
// Start timer for 3rd party security
|
|||
|
//
|
|||
|
|
|||
|
TimerQRemove( (HANDLE)pDeviceObj->hPort, SvSecurityTimeout );
|
|||
|
|
|||
|
TimerQInsert( (HANDLE)pDeviceObj->hPort,
|
|||
|
gblDDMConfigInfo.dwSecurityTime,
|
|||
|
SvSecurityTimeout);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
//*** Array of previous connection state/ current connection state
|
|||
|
// used to select the Ras Manager signaled event handler
|
|||
|
//
|
|||
|
|
|||
|
typedef VOID (* RMEVHDLR)(PDEVICE_OBJECT);
|
|||
|
|
|||
|
typedef struct _RMEHNODE
|
|||
|
{
|
|||
|
RASMAN_STATE previous_state;
|
|||
|
RASMAN_STATE current_state;
|
|||
|
RMEVHDLR rmevhandler;
|
|||
|
|
|||
|
} RMEHNODE, *PRMEHNODE;
|
|||
|
|
|||
|
|
|||
|
RMEHNODE rmehtab[] =
|
|||
|
{
|
|||
|
// Transition
|
|||
|
// Previous --> Current
|
|||
|
|
|||
|
{ CONNECTING, CONNECTED, SvDevConnected },
|
|||
|
{ LISTENING, LISTENCOMPLETED, SvDevListenComplete },
|
|||
|
{ LISTENCOMPLETED, CONNECTED, SvDevConnected },
|
|||
|
{ LISTENCOMPLETED, DISCONNECTED, SvDevDisconnected },
|
|||
|
{ LISTENING, DISCONNECTED, SvDevDisconnected },
|
|||
|
{ CONNECTED, DISCONNECTED, SvDevDisconnected },
|
|||
|
{ DISCONNECTING, DISCONNECTED, SvDevDisconnected },
|
|||
|
{ CONNECTED, CONNECTING, SvDevDisconnected },
|
|||
|
{ 0xffff, 0xffff, NULL }// Table Guard
|
|||
|
};
|
|||
|
|
|||
|
VOID
|
|||
|
RmEventHandler(
|
|||
|
DWORD dwEventIndex
|
|||
|
)
|
|||
|
{
|
|||
|
RASMAN_INFO RasPortInfo;
|
|||
|
PDEVICE_OBJECT pDevObj;
|
|||
|
PRMEHNODE ehnp;
|
|||
|
DWORD dwRetCode;
|
|||
|
DWORD dwBucketIndex = dwEventIndex - NUM_DDM_EVENTS;
|
|||
|
|
|||
|
EnterCriticalSection( &(gblDeviceTable.CriticalSection) );
|
|||
|
|
|||
|
//
|
|||
|
// for each port in this bucket
|
|||
|
//
|
|||
|
|
|||
|
for ( pDevObj = gblDeviceTable.DeviceBucket[dwBucketIndex];
|
|||
|
pDevObj != (DEVICE_OBJECT *)NULL;
|
|||
|
pDevObj = pDevObj->pNext )
|
|||
|
{
|
|||
|
//
|
|||
|
// get the port state
|
|||
|
//
|
|||
|
|
|||
|
dwRetCode = RasGetInfo( NULL, pDevObj->hPort, &RasPortInfo );
|
|||
|
|
|||
|
if ( dwRetCode != NO_ERROR )
|
|||
|
{
|
|||
|
SetLastError( dwRetCode );
|
|||
|
|
|||
|
DDMTRACE3( "RasGetInfo( 0x%x, 0x%x ) = %d",
|
|||
|
pDevObj->hPort, &RasPortInfo, dwRetCode );
|
|||
|
|
|||
|
//
|
|||
|
// Assume the the port is disconnected
|
|||
|
//
|
|||
|
|
|||
|
pDevObj->ConnectionState = DISCONNECTED;
|
|||
|
|
|||
|
SvDevDisconnected( pDevObj );
|
|||
|
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// check if we own the port now
|
|||
|
//
|
|||
|
|
|||
|
if (!RasPortInfo.RI_OwnershipFlag)
|
|||
|
{
|
|||
|
//
|
|||
|
// skip biplexed ports used by other processes
|
|||
|
//
|
|||
|
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// switch on our private connection state
|
|||
|
//
|
|||
|
|
|||
|
switch (pDevObj->ConnectionState)
|
|||
|
{
|
|||
|
case CONNECTING:
|
|||
|
|
|||
|
if (RasPortInfo.RI_ConnState == CONNECTING)
|
|||
|
{
|
|||
|
switch (RasPortInfo.RI_LastError)
|
|||
|
{
|
|||
|
case SUCCESS:
|
|||
|
|
|||
|
RasPortConnectComplete(pDevObj->hPort);
|
|||
|
|
|||
|
//
|
|||
|
// force current state to connected.
|
|||
|
//
|
|||
|
|
|||
|
RasPortInfo.RI_ConnState = CONNECTED;
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
case PENDING:
|
|||
|
|
|||
|
//
|
|||
|
// no action
|
|||
|
//
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
|
|||
|
//
|
|||
|
// error occured -> force state to disconnecting
|
|||
|
//
|
|||
|
|
|||
|
pDevObj->ConnectionState = DISCONNECTING;
|
|||
|
|
|||
|
DDM_PRINT(
|
|||
|
gblDDMConfigInfo.dwTraceId,
|
|||
|
TRACE_FSM,
|
|||
|
"RmEventHandler: RI_LastError indicates error when");
|
|||
|
DDM_PRINT(
|
|||
|
gblDDMConfigInfo.dwTraceId,
|
|||
|
TRACE_FSM,
|
|||
|
" CONNECTING on port %d !!!\n", pDevObj->hPort );
|
|||
|
DDM_PRINT(
|
|||
|
gblDDMConfigInfo.dwTraceId,
|
|||
|
TRACE_FSM,
|
|||
|
"RmEventHandler:RasPortDisconnect posted on port%d\n",
|
|||
|
pDevObj->hPort);
|
|||
|
|
|||
|
if ( pDevObj->DeviceState == DEV_OBJ_CALLBACK_CONNECTING )
|
|||
|
{
|
|||
|
LPWSTR Parms[3];
|
|||
|
WCHAR wchFullUserName[UNLEN+DNLEN+2];
|
|||
|
|
|||
|
if ( pDevObj->wchDomainName[0] != TEXT('\0') )
|
|||
|
{
|
|||
|
wcscpy( wchFullUserName, pDevObj->wchDomainName);
|
|||
|
wcscat( wchFullUserName, TEXT("\\") );
|
|||
|
wcscat( wchFullUserName, pDevObj->wchUserName );
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
wcscpy( wchFullUserName, pDevObj->wchUserName );
|
|||
|
}
|
|||
|
|
|||
|
Parms[0] = wchFullUserName;
|
|||
|
Parms[1] = pDevObj->wchPortName;
|
|||
|
Parms[2] = pDevObj->wchCallbackNumber;
|
|||
|
|
|||
|
DDMLogErrorString(ROUTERLOG_CALLBACK_FAILURE, 3, Parms,
|
|||
|
RasPortInfo.RI_LastError, 3 );
|
|||
|
}
|
|||
|
|
|||
|
dwRetCode = RasPortDisconnect(
|
|||
|
pDevObj->hPort,
|
|||
|
gblSupervisorEvents[NUM_DDM_EVENTS +
|
|||
|
dwBucketIndex ] );
|
|||
|
|
|||
|
RTASSERT((dwRetCode == PENDING) || (dwRetCode == SUCCESS));
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
case LISTENING:
|
|||
|
|
|||
|
if (RasPortInfo.RI_ConnState != LISTENING)
|
|||
|
{
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
switch (RasPortInfo.RI_LastError)
|
|||
|
{
|
|||
|
case PENDING:
|
|||
|
|
|||
|
//
|
|||
|
// no action
|
|||
|
//
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
|
|||
|
//
|
|||
|
// error occured -> force state to disconnecting
|
|||
|
//
|
|||
|
|
|||
|
pDevObj->ConnectionState = DISCONNECTING;
|
|||
|
|
|||
|
DDM_PRINT(
|
|||
|
gblDDMConfigInfo.dwTraceId,
|
|||
|
TRACE_FSM,
|
|||
|
"RmEventHandler: RI_LastError indicates error %d when",
|
|||
|
RasPortInfo.RI_LastError );
|
|||
|
DDM_PRINT(
|
|||
|
gblDDMConfigInfo.dwTraceId,
|
|||
|
TRACE_FSM,
|
|||
|
" LISTENING on port %d !!!\n", pDevObj->hPort );
|
|||
|
DDM_PRINT(
|
|||
|
gblDDMConfigInfo.dwTraceId,
|
|||
|
TRACE_FSM,
|
|||
|
"RmEventHandler:RasPortDisconnect posted on port%d\n",
|
|||
|
pDevObj->hPort);
|
|||
|
|
|||
|
dwRetCode = RasPortDisconnect(
|
|||
|
pDevObj->hPort,
|
|||
|
gblSupervisorEvents[NUM_DDM_EVENTS +
|
|||
|
dwBucketIndex ] );
|
|||
|
|
|||
|
RTASSERT((dwRetCode == PENDING) || (dwRetCode == SUCCESS));
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// try to find the table element with the matching previous and
|
|||
|
// current connection states
|
|||
|
//
|
|||
|
|
|||
|
for (ehnp=rmehtab; ehnp->rmevhandler != NULL; ehnp++)
|
|||
|
{
|
|||
|
if ((ehnp->previous_state == pDevObj->ConnectionState) &&
|
|||
|
(ehnp->current_state == RasPortInfo.RI_ConnState))
|
|||
|
{
|
|||
|
//
|
|||
|
//*** Match ***
|
|||
|
//
|
|||
|
|
|||
|
DDM_PRINT(
|
|||
|
gblDDMConfigInfo.dwTraceId,
|
|||
|
TRACE_FSM,
|
|||
|
"Rasman state change received from port %d, %d->%d",
|
|||
|
pDevObj->hPort, ehnp->previous_state, ehnp->current_state );
|
|||
|
|
|||
|
//
|
|||
|
// change the dcb conn state (previous state) with the
|
|||
|
// current state
|
|||
|
//
|
|||
|
|
|||
|
pDevObj->ConnectionState = RasPortInfo.RI_ConnState;
|
|||
|
|
|||
|
//
|
|||
|
// invoke the handler
|
|||
|
//
|
|||
|
|
|||
|
(*ehnp->rmevhandler)(pDevObj);
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
LeaveCriticalSection( &(gblDeviceTable.CriticalSection) );
|
|||
|
}
|
|||
|
|
|||
|
//***
|
|||
|
//
|
|||
|
// Function: SvFrameReceived
|
|||
|
//
|
|||
|
// Descr: starts authentication
|
|||
|
//
|
|||
|
//***
|
|||
|
VOID
|
|||
|
SvFrameReceived(
|
|||
|
IN PDEVICE_OBJECT pDeviceObj,
|
|||
|
IN CHAR *framep, // pointer to the received frame
|
|||
|
IN DWORD framelen,
|
|||
|
IN DWORD dwBucketIndex
|
|||
|
)
|
|||
|
{
|
|||
|
DWORD dwRetCode;
|
|||
|
DWORD FrameType;
|
|||
|
LPWSTR portnamep;
|
|||
|
PCONNECTION_OBJECT pConnObj;
|
|||
|
BYTE RecvBuffer[1500];
|
|||
|
|
|||
|
DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM,
|
|||
|
"SvFrameReceived: Entered, hPort: %d", pDeviceObj->hPort);
|
|||
|
|
|||
|
if ( framelen > sizeof( RecvBuffer ) )
|
|||
|
{
|
|||
|
DDMTRACE2( "Illegal frame length of %d received for port %d",
|
|||
|
framelen, pDeviceObj->hPort );
|
|||
|
|
|||
|
RTASSERT( FALSE );
|
|||
|
|
|||
|
//
|
|||
|
// Frame length is illegal so truncate it
|
|||
|
//
|
|||
|
|
|||
|
framelen = sizeof( RecvBuffer );
|
|||
|
}
|
|||
|
|
|||
|
memcpy( RecvBuffer, framep, framelen);
|
|||
|
|
|||
|
switch (pDeviceObj->DeviceState)
|
|||
|
{
|
|||
|
case DEV_OBJ_RECEIVING_FRAME:
|
|||
|
|
|||
|
if ( !DDMRecognizeFrame( RecvBuffer, (WORD)framelen, &FrameType) )
|
|||
|
{
|
|||
|
portnamep = pDeviceObj->wchPortName;
|
|||
|
|
|||
|
DDMLogError(ROUTERLOG_UNRECOGNIZABLE_FRAME_RECVD, 1, &portnamep, 0);
|
|||
|
|
|||
|
DevStartClosing(pDeviceObj);
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// check first with our authentication module
|
|||
|
//
|
|||
|
|
|||
|
switch( FrameType )
|
|||
|
{
|
|||
|
|
|||
|
case PPP_LCP_PROTOCOL:
|
|||
|
|
|||
|
pDeviceObj->fFlags |= DEV_OBJ_IS_PPP;
|
|||
|
|
|||
|
DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM,
|
|||
|
"SvFrameReceived: PPP frame on port %d",
|
|||
|
pDeviceObj->hPort);
|
|||
|
|
|||
|
dwRetCode = PppDdmStart( pDeviceObj->hPort,
|
|||
|
pDeviceObj->wchPortName,
|
|||
|
RecvBuffer,
|
|||
|
framelen,
|
|||
|
gblDDMConfigInfo.dwAuthenticateRetries
|
|||
|
);
|
|||
|
|
|||
|
if ( dwRetCode != NO_ERROR )
|
|||
|
{
|
|||
|
portnamep = pDeviceObj->wchPortName;
|
|||
|
|
|||
|
DDMLogErrorString( ROUTERLOG_CANT_START_PPP, 1, &portnamep,
|
|||
|
dwRetCode,1);
|
|||
|
|
|||
|
DevStartClosing(pDeviceObj);
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
case APPLETALK:
|
|||
|
|
|||
|
DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM,
|
|||
|
"SvFrameReceived: protocol not supported! %d",
|
|||
|
pDeviceObj->hPort);
|
|||
|
|
|||
|
RTASSERT( FALSE );
|
|||
|
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// auth has started OK. Update state
|
|||
|
// start auth timer
|
|||
|
//
|
|||
|
|
|||
|
pDeviceObj->DeviceState = DEV_OBJ_AUTH_IS_ACTIVE;
|
|||
|
pDeviceObj->fFlags |= DEV_OBJ_AUTH_ACTIVE;
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
case DEV_OBJ_CLOSING:
|
|||
|
|
|||
|
DevCloseComplete(pDeviceObj);
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
//***
|
|||
|
//
|
|||
|
// Function: RmRecvFrameEventHandler
|
|||
|
//
|
|||
|
// Description: Scans the set of opened ports and detects the ports where
|
|||
|
// RasPortReceive has completed. Invokes the FSM handling
|
|||
|
// procedure for each detected port and frees the receive
|
|||
|
// buffer.
|
|||
|
//
|
|||
|
//***
|
|||
|
VOID
|
|||
|
RmRecvFrameEventHandler(
|
|||
|
DWORD dwEventIndex
|
|||
|
)
|
|||
|
{
|
|||
|
PDEVICE_OBJECT pDevObj;
|
|||
|
RASMAN_INFO RasPortInfo;
|
|||
|
DWORD dwRetCode;
|
|||
|
DWORD dwBucketIndex = dwEventIndex
|
|||
|
- NUM_DDM_EVENTS
|
|||
|
- gblDeviceTable.NumDeviceBuckets;
|
|||
|
|
|||
|
EnterCriticalSection( &(gblDeviceTable.CriticalSection) );
|
|||
|
|
|||
|
//
|
|||
|
// for each port in this bucket
|
|||
|
//
|
|||
|
|
|||
|
for ( pDevObj = gblDeviceTable.DeviceBucket[dwBucketIndex];
|
|||
|
pDevObj != (DEVICE_OBJECT *)NULL;
|
|||
|
pDevObj = pDevObj->pNext )
|
|||
|
{
|
|||
|
//
|
|||
|
// get the port state
|
|||
|
//
|
|||
|
|
|||
|
dwRetCode = RasGetInfo( NULL, pDevObj->hPort, &RasPortInfo );
|
|||
|
|
|||
|
if ( dwRetCode != NO_ERROR )
|
|||
|
{
|
|||
|
//
|
|||
|
// Assume port is disconncted, so clean up
|
|||
|
//
|
|||
|
|
|||
|
DevStartClosing(pDevObj);
|
|||
|
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// check if we own the port now
|
|||
|
//
|
|||
|
|
|||
|
if (!RasPortInfo.RI_OwnershipFlag)
|
|||
|
{
|
|||
|
//
|
|||
|
// skip biplexed ports used by other processes
|
|||
|
//
|
|||
|
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
if ( ( pDevObj->fFlags & DEV_OBJ_RECEIVE_ACTIVE ) &&
|
|||
|
( RasPortInfo.RI_LastError != PENDING ) )
|
|||
|
{
|
|||
|
//
|
|||
|
// recv frame API has completed
|
|||
|
//
|
|||
|
|
|||
|
pDevObj->fFlags &= (~DEV_OBJ_RECEIVE_ACTIVE );
|
|||
|
|
|||
|
if ( RasPortInfo.RI_LastError != ERROR_PORT_DISCONNECTED )
|
|||
|
{
|
|||
|
LPBYTE lpBuffer = LocalAlloc(LPTR,RasPortInfo.RI_BytesReceived);
|
|||
|
|
|||
|
if ( lpBuffer == NULL )
|
|||
|
{
|
|||
|
DevStartClosing(pDevObj);
|
|||
|
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
memcpy( lpBuffer,
|
|||
|
pDevObj->pRasmanRecvBuffer,
|
|||
|
RasPortInfo.RI_BytesReceived );
|
|||
|
|
|||
|
RasFreeBuffer(pDevObj->pRasmanRecvBuffer);
|
|||
|
|
|||
|
pDevObj->pRasmanRecvBuffer = NULL;
|
|||
|
|
|||
|
//
|
|||
|
// call the FSM handler
|
|||
|
//
|
|||
|
|
|||
|
SvFrameReceived( pDevObj,
|
|||
|
lpBuffer,
|
|||
|
RasPortInfo.RI_BytesReceived,
|
|||
|
dwBucketIndex);
|
|||
|
|
|||
|
LocalFree( lpBuffer );
|
|||
|
}
|
|||
|
|
|||
|
if ( pDevObj->pRasmanRecvBuffer != NULL )
|
|||
|
{
|
|||
|
RasFreeBuffer(pDevObj->pRasmanRecvBuffer);
|
|||
|
|
|||
|
pDevObj->pRasmanRecvBuffer = NULL;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
LeaveCriticalSection( &(gblDeviceTable.CriticalSection) );
|
|||
|
}
|
|||
|
|
|||
|
|