|
|
/********************************************************************/ /** Copyright(c) 1995 Microsoft Corporation. **/ /********************************************************************/
//***
//
// Filename: ifobject.c
//
// Description: Routines to manipulate ROUTER_INTERFACE_OBJECTs
//
// History: May 11,1995 NarenG Created original version.
//
#include "ddm.h"
#include "objects.h"
#include "handlers.h"
#include "timer.h"
#include <util.h>
#include <rasapiif.h>
#include <ras.h>
typedef struct _DDM_SUBENTRY_ENUMCONTEXT { ROUTER_INTERFACE_OBJECT *pIfObject; BOOL fAtLeastOneDeviceAvailable; } DDM_SUBENTRY_ENUMCONTEXT;
//
// This actually lives in rasapi.dll
//
DWORD DDMGetPhonebookInfo( LPWSTR lpwsPhonebookName, LPWSTR lpwsPhonebookEntry, LPDWORD lpdwNumSubEntries, LPDWORD lpdwNumRedialAttempts, LPDWORD lpdwNumSecondsBetweenAttempts, BOOL * lpfRedialOnLinkFailure, CHAR * szzParameters, LPDWORD lpdwDialMode, PVOID * ppvContext, PVOID pvSubEntryEnumHandler, PVOID pvSubEntryEnumHandlerContext );
VOID DDMFreePhonebookContext( VOID *pvContext );
VOID DDMEnumerateSubEntries( PVOID pvContext, LPWSTR pwsInterfaceName, FARPROC IfObjectSubEntryEnumHandler, VOID *pvEnumContext );
RASEVENT * DDMGetRasEvent(HCONN hConnection) { CONNECTION_OBJECT *pConn = NULL; RASEVENT *pEvent; pEvent = (RASEVENT *) LOCAL_ALLOC(LPTR, sizeof(RASEVENT)); if(pEvent != NULL) { pConn = ConnObjGetPointer(hConnection);
if(pConn != NULL) { if( pConn->pDeviceList && pConn->pDeviceList[0]) { pEvent->rDeviceType = pConn->pDeviceList[0]->dwDeviceType; } CopyMemory(&pEvent->guidId, &pConn->guid, sizeof(GUID)); pEvent->hConnection = hConnection; } } return pEvent; }
//**
//
// Call: IfObjectAllocateAndInit
//
// Returns: ROUTER_INTERFACE_OBJECT * - Success
// NULL - Failure
//
// Description: Allocates and initializes a ROUTER_INTERFACE_OBJECT structure
//
ROUTER_INTERFACE_OBJECT * IfObjectAllocateAndInit( IN LPWSTR lpwstrName, IN ROUTER_INTERFACE_STATE State, IN ROUTER_INTERFACE_TYPE IfType, IN HCONN hConnection, IN BOOL fEnabled, IN DWORD dwMinUnreachabilityInterval, IN DWORD dwMaxUnreachabilityInterval, IN LPWSTR lpwsDialoutHours, IN OUT PVOID * ppvContext ) { return( ( (ROUTER_INTERFACE_OBJECT*(*)( LPWSTR, ROUTER_INTERFACE_STATE, ROUTER_INTERFACE_TYPE, HCONN, BOOL, DWORD, DWORD, LPWSTR, PVOID *))gblDDMConfigInfo.lpfnIfObjectAllocateAndInit)( lpwstrName, State, IfType, hConnection, fEnabled, dwMinUnreachabilityInterval, dwMaxUnreachabilityInterval, lpwsDialoutHours, NULL));
}
//**
//
// Call: IfObjectAreAllTransportsDisconnected
//
// Returns: TRUE
// FALSE
//
// Description: Checks to see if all the transports for an interface are
// disconnected.
//
BOOL IfObjectAreAllTransportsDisconnected( IN ROUTER_INTERFACE_OBJECT * pIfObject ) { DWORD dwTransportIndex;
for ( dwTransportIndex = 0; dwTransportIndex < gblDDMConfigInfo.dwNumRouterManagers; dwTransportIndex++ ) { if ( pIfObject->Transport[dwTransportIndex].fState & RITRANSPORT_CONNECTED ) { return( FALSE ); } }
return( TRUE ); }
//**
//
// Call: IfObjectGetPointerByName
//
// Returns: ROUTER_INTERFACE_OBJECT * - Pointer to the interface object
// structure with the given name, if it exists.
// NULL - if it doesn't exist.
//
// Description: Simply calls the DIM entry point to do the work.
//
ROUTER_INTERFACE_OBJECT * IfObjectGetPointerByName( IN LPWSTR lpwstrName, IN BOOL fIncludeClientInterfaces ) { return(((ROUTER_INTERFACE_OBJECT*(*)( LPWSTR, BOOL )) gblDDMConfigInfo.lpfnIfObjectGetPointerByName)( lpwstrName, fIncludeClientInterfaces)); }
//**
//
// Call: IfObjectGetPointer
//
// Returns: ROUTER_INTERFACE_OBJECT * - Pointer to the interface object
// structure with the given handle, if it exists.
// NULL - if it doesn't exist.
//
// Description: Simply calls the DIM entry point to do the work.
//
ROUTER_INTERFACE_OBJECT * IfObjectGetPointer( IN HANDLE hDIMInterface ) { return(((ROUTER_INTERFACE_OBJECT*(*)( HANDLE )) gblDDMConfigInfo.lpfnIfObjectGetPointer)( hDIMInterface )); }
//**
//
// Call: IfObjectRemove
//
// Returns: None
//
// Description: Simply calls the DIM entrypoint to remove the interface object
// from the table. The object is DeAllocated.
//
VOID IfObjectRemove( IN HANDLE hDIMInterface ) { ((VOID(*)( HANDLE ))gblDDMConfigInfo.lpfnIfObjectRemove)( hDIMInterface ); }
//**
//
// Call: IfObjectDisconnected
//
// Returns: None
//
// Description: Sets this interface to the disconnected state
//
VOID IfObjectDisconnected( ROUTER_INTERFACE_OBJECT * pIfObject ) { DWORD dwIndex; BOOL fReachable = TRUE; HANDLE hConnection;
//
// If already disconnected, then simply return
//
if ( pIfObject->State == RISTATE_DISCONNECTED ) { return; }
//
// If this interface is persistent then we do not want to connect
// again because the local admin or router managers initiated the
// disconnect
//
if ( pIfObject->fFlags & IFFLAG_DISCONNECT_INITIATED ) { pIfObject->dwNumOfReConnectAttemptsCounter = 0;
TimerQRemove( pIfObject->hDIMInterface, ReConnectInterface );
TimerQRemove( pIfObject->hDIMInterface, ReConnectPersistentInterface ); }
hConnection = pIfObject->hConnection; pIfObject->State = RISTATE_DISCONNECTED; pIfObject->hConnection = (HCONN)INVALID_HANDLE_VALUE; pIfObject->fFlags &= ~IFFLAG_LOCALLY_INITIATED; pIfObject->hRasConn = (HRASCONN)NULL;
//
// If we are not unreachable due to connection failure
//
if ( !( pIfObject->fFlags & IFFLAG_CONNECTION_FAILURE ) ) { //
// Check reachability state
//
DWORD dwUnreachabilityReason;
if ( pIfObject->fFlags & IFFLAG_OUT_OF_RESOURCES ) { dwUnreachabilityReason = INTERFACE_OUT_OF_RESOURCES; fReachable = FALSE; } else if ( gblDDMConfigInfo.pServiceStatus->dwCurrentState == SERVICE_PAUSED ) { dwUnreachabilityReason = INTERFACE_SERVICE_IS_PAUSED; fReachable = FALSE; } else if ( !( pIfObject->fFlags & IFFLAG_ENABLED ) ) { dwUnreachabilityReason = INTERFACE_DISABLED; fReachable = FALSE; } else if ( pIfObject->fFlags & IFFLAG_DIALOUT_HOURS_RESTRICTION ) { dwUnreachabilityReason = INTERFACE_DIALOUT_HOURS_RESTRICTION; fReachable = FALSE; }
//
// Notify the router manager that this interface is disabled if the
// admin has disabled it or the service is paused, now that the
// interface is disconnected.
//
for ( dwIndex = 0; dwIndex < gblDDMConfigInfo.dwNumRouterManagers; dwIndex++ ) { pIfObject->Transport[dwIndex].fState &= ~RITRANSPORT_CONNECTED;
if ( !fReachable ) { if (pIfObject->Transport[dwIndex].hInterface == INVALID_HANDLE_VALUE) { continue; }
gblRouterManagers[dwIndex].DdmRouterIf.InterfaceNotReachable( pIfObject->Transport[dwIndex].hInterface, dwUnreachabilityReason ); } }
if ( !fReachable ) { if ( pIfObject->IfType == ROUTER_IF_TYPE_FULL_ROUTER ) { LogUnreachabilityEvent( dwUnreachabilityReason, pIfObject->lpwsInterfaceName ); } }
//
// If this interface is marked as persistent then try to reconnect
// only if the admin did not disconnect the interface
//
if ( ( fReachable ) && ( pIfObject->fFlags & IFFLAG_PERSISTENT ) && ( !( pIfObject->fFlags & IFFLAG_DISCONNECT_INITIATED ) ) ) { TimerQInsert( pIfObject->hDIMInterface, 1, ReConnectPersistentInterface ); }
//
// Notify that this connection has been disconnected
//
IfObjectConnectionChangeNotification();
{ //
// Notify netman that a connection went down.
//
DWORD retcode; RASEVENT *pRasEvent = NULL; CONNECTION_OBJECT *pConn = NULL;
pRasEvent = DDMGetRasEvent(hConnection);
if(pRasEvent != NULL) { pRasEvent->Type = INCOMING_DISCONNECTED; retcode = RasSendNotification(pRasEvent);
DDM_PRINT(gblDDMConfigInfo.dwTraceId, TRACE_FSM, "RasSendNotification(INCOMING_DISCONNETED rc=0x%x", retcode);
LOCAL_FREE(pRasEvent); } }
} }
//**
//
// Call: IfObjectConnected
//
// Returns: None
//
// Description: Sets this interface to the CONNECTED state and notifies the
// router managers, if any, about unreachable transports.
//
DWORD IfObjectConnected( IN HANDLE hDDMInterface, IN HCONN hConnection, IN PPP_PROJECTION_RESULT *pProjectionResult ) { DWORD dwIndex; ROUTER_INTERFACE_OBJECT * pIfObject; BOOL fXportConnected = FALSE;
EnterCriticalSection( &(gblpInterfaceTable->CriticalSection) );
pIfObject = IfObjectGetPointer( hDDMInterface );
if ( pIfObject == (ROUTER_INTERFACE_OBJECT *)NULL ) { LeaveCriticalSection( &(gblpInterfaceTable->CriticalSection) );
return( ERROR_INVALID_HANDLE ); }
if ( pIfObject->State == RISTATE_CONNECTED ) { //
// Already connected
//
LeaveCriticalSection( &(gblpInterfaceTable->CriticalSection) );
return( NO_ERROR ); }
pIfObject->hConnection = hConnection; pIfObject->State = RISTATE_CONNECTED; pIfObject->fFlags &= ~IFFLAG_CONNECTION_FAILURE;
//
// If we are connected and we initiated the connection then reset the
// unreachability interval
//
if ( pIfObject->fFlags & IFFLAG_LOCALLY_INITIATED ) { pIfObject->dwReachableAfterSeconds = pIfObject->dwReachableAfterSecondsMin; }
//
// Remove any reconnect calls that may be on the timer queue
//
TimerQRemove( pIfObject->hDIMInterface, ReConnectInterface ); TimerQRemove( pIfObject->hDIMInterface, ReConnectPersistentInterface );
for ( dwIndex = 0; dwIndex < gblDDMConfigInfo.dwNumRouterManagers; dwIndex++ ) { fXportConnected = FALSE;
switch( gblRouterManagers[dwIndex].DdmRouterIf.dwProtocolId ) { case PID_IPX:
if ( pProjectionResult->ipx.dwError == NO_ERROR ) { fXportConnected = TRUE;
}
break;
case PID_IP:
if ( pProjectionResult->ip.dwError == NO_ERROR ) { fXportConnected = TRUE; }
break;
default:
break; }
if ( pIfObject->Transport[dwIndex].hInterface == INVALID_HANDLE_VALUE ) { continue; }
if ( fXportConnected ) { DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM, "Notifying Protocol = 0x%x,Interface=%ws is Connected", gblRouterManagers[dwIndex].DdmRouterIf.dwProtocolId, pIfObject->lpwsInterfaceName );
pIfObject->Transport[dwIndex].fState |= RITRANSPORT_CONNECTED;
gblRouterManagers[dwIndex].DdmRouterIf.InterfaceConnected( pIfObject->Transport[dwIndex].hInterface, NULL, pProjectionResult ); } else { DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM, "Notifying Protocol = 0x%x,Interface=%ws is UnReachable=%d", gblRouterManagers[dwIndex].DdmRouterIf.dwProtocolId, pIfObject->lpwsInterfaceName, INTERFACE_CONNECTION_FAILURE );
gblRouterManagers[dwIndex].DdmRouterIf.InterfaceNotReachable( pIfObject->Transport[dwIndex].hInterface, INTERFACE_CONNECTION_FAILURE ); } }
IfObjectConnectionChangeNotification();
LeaveCriticalSection( &(gblpInterfaceTable->CriticalSection) ); { DWORD retcode; RASEVENT *pRasEvent = NULL; CONNECTION_OBJECT *pConn = NULL;
//
// Get the device type
//
EnterCriticalSection(&(gblDeviceTable.CriticalSection)); pRasEvent = DDMGetRasEvent(hConnection); LeaveCriticalSection(&(gblDeviceTable.CriticalSection));
if(pRasEvent != NULL) { //
// Notify netman of the connection
//
pRasEvent->Type = INCOMING_CONNECTED; retcode = RasSendNotification(pRasEvent);
DDM_PRINT(gblDDMConfigInfo.dwTraceId, TRACE_FSM, "RasSendNotification(ENTRY_CONNECTED) rc=0x%x", retcode);
LOCAL_FREE(pRasEvent); } }
return( NO_ERROR ); }
//**
//
// Call: IfObjectComputeReachableDelay
//
// Returns: The delay
//
// Description: Computes the next reachability delay based on the
// current one. Following is the sequenced used:
//
// min, 10, 20, 35, 50, 65, 90, 120, 120, 120, ...
//
// The reachability delay is used to govern when to
// re-attempt to connect an interface that in the
// past was unable to connect (presumably because of
// an error on the other side).
//
// In Win2k, the sequence was x0=min, xi = (xi-1 * 2)
// This sequence was found to be problematic because
// the increase was so steep that it was common in
// installations with many interfaces to find interfaces
// that wouldn't be retried for days.
//
// The new sequence is designed to max out at two hours.
// If an interface is expected to be unreachable for more
// than two hours at a time, then a dialout hours restriction
// should be used to achieve the desired effect.
//
DWORD IfObjectComputeReachableDelay( IN ROUTER_INTERFACE_OBJECT * pIfObject) { DWORD dwSeconds = 0;
if (pIfObject->dwReachableAfterSeconds == pIfObject->dwReachableAfterSecondsMin) { dwSeconds = 600; }
switch (pIfObject->dwReachableAfterSeconds) { case 10*60: dwSeconds = 20*60; break; case 20*60: dwSeconds = 35*60; break; case 35*60: dwSeconds = 50*60; break; case 50*60: dwSeconds = 65*60; break; case 65*60: dwSeconds = 90*60; break; case 90*60: case 120*60: dwSeconds = 120*60; break; }
return dwSeconds; }
//**
//
// Call: IfObjectNotifyOfReachabilityChange
//
// Returns: None
//
// Description: Notifies the object of change in reachablity status.
//
//
VOID IfObjectNotifyOfReachabilityChange( IN ROUTER_INTERFACE_OBJECT * pIfObject, IN BOOL fReachable, IN UNREACHABILITY_REASON dwReason ) { DWORD dwIndex;
if ( pIfObject->IfType != ROUTER_IF_TYPE_FULL_ROUTER ) { return; }
if ( pIfObject->State != RISTATE_DISCONNECTED ) { return; } switch( dwReason ) { case INTERFACE_SERVICE_IS_PAUSED:
//
// Check if we are unreachable due to other reasons as well, if we
// are, then no need to notify this object of (un)reachability.
//
if ( pIfObject->fFlags & IFFLAG_OUT_OF_RESOURCES ) { return; }
if ( !( pIfObject->fFlags & IFFLAG_ENABLED ) ) { return; }
if ( pIfObject->fFlags & IFFLAG_CONNECTION_FAILURE ) { return; }
if ( pIfObject->fFlags & IFFLAG_DIALOUT_HOURS_RESTRICTION ) { return; }
break;
case INTERFACE_CONNECTION_FAILURE:
//
// If we are marking this interface as not reachable due to connection
// failure then we will mark as reachable after dwReachableAfterSeconds
//
if ( !fReachable ) { //
// Don't do this if the admin disconnected the interface
//
if ( !( pIfObject->fFlags & IFFLAG_DISCONNECT_INITIATED ) ) { DWORD dwDelay, dwTime, dwDelta, dwCur;
dwCur = pIfObject->dwReachableAfterSeconds; dwDelay = IfObjectComputeReachableDelay(pIfObject); dwDelta = (dwDelay > dwCur) ? dwDelay - dwCur : 0;
if (dwDelta != 0) { dwTime = dwCur + (GetTickCount() % dwDelta); } else { dwTime = dwCur; }
DDMTRACE2( "Will mark interface %ws as reachable after %d seconds", pIfObject->lpwsInterfaceName, dwTime );
TimerQInsert( pIfObject->hDIMInterface, dwTime, MarkInterfaceAsReachable);
if (dwDelay < pIfObject->dwReachableAfterSecondsMax) { pIfObject->dwReachableAfterSeconds = dwDelay; } } } else { //
// Notify of reachability only if the interface is reachable
//
if ( pIfObject->fFlags & IFFLAG_OUT_OF_RESOURCES ) { return; }
if ( gblDDMConfigInfo.pServiceStatus->dwCurrentState == SERVICE_PAUSED ) { return; }
if ( !( pIfObject->fFlags & IFFLAG_ENABLED ) ) { return; }
if ( pIfObject->fFlags & IFFLAG_DIALOUT_HOURS_RESTRICTION ) { return; } }
break;
case INTERFACE_DISABLED:
if ( pIfObject->fFlags & IFFLAG_OUT_OF_RESOURCES ) { return; }
if ( gblDDMConfigInfo.pServiceStatus->dwCurrentState == SERVICE_PAUSED ) { return; }
if ( pIfObject->fFlags & IFFLAG_CONNECTION_FAILURE ) { return; }
if ( pIfObject->fFlags & IFFLAG_DIALOUT_HOURS_RESTRICTION ) { return; } break;
case INTERFACE_OUT_OF_RESOURCES:
if ( gblDDMConfigInfo.pServiceStatus->dwCurrentState == SERVICE_PAUSED ) { return; }
if ( !( pIfObject->fFlags & IFFLAG_ENABLED ) ) { return; }
if ( pIfObject->fFlags & IFFLAG_CONNECTION_FAILURE ) { return; }
if ( pIfObject->fFlags & IFFLAG_DIALOUT_HOURS_RESTRICTION ) { return; }
break;
case INTERFACE_DIALOUT_HOURS_RESTRICTION: if ( gblDDMConfigInfo.pServiceStatus->dwCurrentState == SERVICE_PAUSED ) { return; }
if ( !( pIfObject->fFlags & IFFLAG_ENABLED ) ) { return; }
if ( pIfObject->fFlags & IFFLAG_CONNECTION_FAILURE ) { return; }
if ( pIfObject->fFlags & IFFLAG_OUT_OF_RESOURCES ) { return; }
break; default: RTASSERT( FALSE );
break; }
for ( dwIndex = 0; dwIndex < gblDDMConfigInfo.dwNumRouterManagers; dwIndex++ ) { if ( pIfObject->Transport[dwIndex].hInterface == INVALID_HANDLE_VALUE ) { continue; }
if ( fReachable ) { DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM, "Notifying Protocol = 0x%x, Interface=%ws is Reachable", gblRouterManagers[dwIndex].DdmRouterIf.dwProtocolId, pIfObject->lpwsInterfaceName );
gblRouterManagers[dwIndex].DdmRouterIf.InterfaceReachable( pIfObject->Transport[dwIndex].hInterface );
} else { DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM, "Notifying Protocol = 0x%x,Interface=%ws is UnReachable=%d", gblRouterManagers[dwIndex].DdmRouterIf.dwProtocolId, pIfObject->lpwsInterfaceName, dwReason );
gblRouterManagers[dwIndex].DdmRouterIf.InterfaceNotReachable( pIfObject->Transport[dwIndex].hInterface, dwReason ); } }
if ( pIfObject->IfType == ROUTER_IF_TYPE_FULL_ROUTER ) { if ( fReachable ) { DDMLogInformation(ROUTERLOG_IF_REACHABLE,1,&(pIfObject->lpwsInterfaceName)); } else { LogUnreachabilityEvent( dwReason, pIfObject->lpwsInterfaceName ); } }
//
// If this interface is reachable, and it is persistent and it has not
// been disconnected by the administrator, then attempt to reconnect now
//
if ( ( pIfObject->fFlags & IFFLAG_PERSISTENT ) && ( fReachable ) && ( !( pIfObject->fFlags & IFFLAG_DISCONNECT_INITIATED ) ) ) { TimerQInsert(pIfObject->hDIMInterface,1,ReConnectPersistentInterface); } }
//**
//
// Call: IfObjectNotifyAllOfReachabilityChange
//
// Returns: None
//
// Description: Check to see if need to run through all the interfaces and
// notify the ones that are not un\reachable now.
//
//
VOID IfObjectNotifyAllOfReachabilityChange( IN BOOL fReachable, IN UNREACHABILITY_REASON dwReason ) { DWORD dwBucketIndex; ROUTER_INTERFACE_OBJECT * pIfObject; DWORD fAvailableMedia; BOOL fNotify;
if ( dwReason == INTERFACE_OUT_OF_RESOURCES ) { //
// No need to notify
//
if ( !gblMediaTable.fCheckInterfaces ) { return; }
gblMediaTable.fCheckInterfaces = FALSE;
MediaObjGetAvailableMediaBits( &fAvailableMedia ); }
for ( dwBucketIndex = 0; dwBucketIndex < NUM_IF_BUCKETS; dwBucketIndex++ ) { for( pIfObject = gblpInterfaceTable->IfBucket[dwBucketIndex]; pIfObject != (ROUTER_INTERFACE_OBJECT *)NULL; pIfObject = pIfObject->pNext ) { fNotify = TRUE;
if ( dwReason == INTERFACE_OUT_OF_RESOURCES ) { fNotify = FALSE;
if ((pIfObject->fMediaUsed & fAvailableMedia) && fReachable ) { //
// If previously unreachable, mark as reachable
//
if ( pIfObject->fFlags & IFFLAG_OUT_OF_RESOURCES ) { pIfObject->fFlags &= ~IFFLAG_OUT_OF_RESOURCES;
fNotify = TRUE; } }
if ((!(pIfObject->fMediaUsed & fAvailableMedia)) && !fReachable) { //
// If previously reachable and currently disconnected,
// mark as unreachable
//
if ( ( !( pIfObject->fFlags & IFFLAG_OUT_OF_RESOURCES ) ) && ( pIfObject->State == RISTATE_DISCONNECTED ) ) { pIfObject->fFlags |= IFFLAG_OUT_OF_RESOURCES;
fNotify = TRUE; } } }
if ( fNotify ) { IfObjectNotifyOfReachabilityChange( pIfObject, fReachable, dwReason ); } } } }
//**
//
// Call: IfObjectAddClientInterface
//
// Returns: None
//
// Description: Add this client interface with all the router managers.
//
//
DWORD IfObjectAddClientInterface( IN ROUTER_INTERFACE_OBJECT * pIfObject, IN PBYTE pClientStaticRoutes ) { DWORD dwIndex; DIM_ROUTER_INTERFACE * pDdmRouterIf; DWORD dwRetCode = NO_ERROR;
for ( dwIndex = 0; dwIndex < gblDDMConfigInfo.dwNumRouterManagers; dwIndex++ ) { pDdmRouterIf=&(gblRouterManagers[dwIndex].DdmRouterIf);
if ( ( pDdmRouterIf->dwProtocolId == PID_IP ) && ( pClientStaticRoutes != NULL ) ) { dwRetCode = pDdmRouterIf->AddInterface( pIfObject->lpwsInterfaceName, pClientStaticRoutes, pIfObject->IfType, pIfObject->hDIMInterface, &(pIfObject->Transport[dwIndex].hInterface)); } else { dwRetCode = pDdmRouterIf->AddInterface( pIfObject->lpwsInterfaceName, gblRouterManagers[dwIndex].pDefaultClientInterface, pIfObject->IfType, pIfObject->hDIMInterface, &(pIfObject->Transport[dwIndex].hInterface)); }
if ( dwRetCode != NO_ERROR ) { LPWSTR lpwsInsertStrings[2]; lpwsInsertStrings[0] = pIfObject->lpwsInterfaceName; lpwsInsertStrings[1] = ( pDdmRouterIf->dwProtocolId == PID_IP ) ? L"IP" : L"IPX"; DDMLogErrorString( ROUTERLOG_COULDNT_ADD_INTERFACE, 2, lpwsInsertStrings, dwRetCode, 2 );
pIfObject->Transport[dwIndex].hInterface = INVALID_HANDLE_VALUE;
break; } }
if ( dwRetCode != NO_ERROR ) { //
// Unload this interface for all the router managers that we loaded.
//
while ( dwIndex-- > 0 ) { pDdmRouterIf=&(gblRouterManagers[dwIndex].DdmRouterIf);
pDdmRouterIf->DeleteInterface( pIfObject->Transport[dwIndex].hInterface );
pIfObject->Transport[dwIndex].hInterface = INVALID_HANDLE_VALUE; } }
return( dwRetCode ); }
//**
//
// Call: IfObjectDeleteInterface
//
// Returns: None
//
// Description: Delete this interface with all the router managers.
//
//
VOID IfObjectDeleteInterface( ROUTER_INTERFACE_OBJECT * pIfObject ) { DWORD dwIndex; DIM_ROUTER_INTERFACE * pDdmRouterIf; DWORD dwRetCode;
for ( dwIndex = 0; dwIndex < gblDDMConfigInfo.dwNumRouterManagers; dwIndex++ ) { if ( pIfObject->Transport[dwIndex].hInterface == INVALID_HANDLE_VALUE ) { continue; }
pDdmRouterIf=&(gblRouterManagers[dwIndex].DdmRouterIf);
dwRetCode = pDdmRouterIf->DeleteInterface( pIfObject->Transport[dwIndex].hInterface );
if ( dwRetCode != NO_ERROR ) { LPWSTR lpwsInsertStrings[2];
lpwsInsertStrings[0] = pIfObject->lpwsInterfaceName; lpwsInsertStrings[1] = ( pDdmRouterIf->dwProtocolId == PID_IP ) ? L"IP" : L"IPX";
DDMLogErrorString( ROUTERLOG_COULDNT_REMOVE_INTERFACE, 2, lpwsInsertStrings, dwRetCode, 2 );
} } }
//**
//
// Call: IfObjectInsertInTable
//
// Returns: None
//
// Description: Simply calls the DIM entrypoint to insert an interface object
// into the interfaec table.
//
DWORD IfObjectInsertInTable( IN ROUTER_INTERFACE_OBJECT * pIfObject ) { return( ((DWORD(*)(ROUTER_INTERFACE_OBJECT *)) gblDDMConfigInfo.lpfnIfObjectInsertInTable)( pIfObject ) ); }
VOID IfObjectSubEntryEnumHandler(PVOID pvContext, WCHAR *pszDeviceType) { DDM_SUBENTRY_ENUMCONTEXT *pContext = (DDM_SUBENTRY_ENUMCONTEXT *)pvContext; DWORD dwRetCode; if(NULL == pContext) { return; }
dwRetCode = MediaObjSetMediaBit(pszDeviceType, &(pContext->pIfObject->fMediaUsed));
if ( dwRetCode == NO_ERROR ) { pContext->fAtLeastOneDeviceAvailable = TRUE; } }
VOID IfObjectFreePhonebookContext(IN VOID *pvContext) { DDMFreePhonebookContext(pvContext); }
//**
//
// Call: IfObjectLoadPhonebookInfo
//
// Returns: NO_ERROR - Success
// Non-zero returns - Failure
//
// Description: Will read the phonebook entry for this interface and set
// bits for a device type used and all other phonebook information
// used.
//
DWORD IfObjectLoadPhonebookInfo( IN ROUTER_INTERFACE_OBJECT * pIfObject, IN OUT PVOID *ppvContext ) { LPRASENTRY pRasEntry = NULL; LPRASSUBENTRY pRasSubEntry = NULL; DWORD dwRetCode = NO_ERROR; DWORD dwIndex; DWORD dwSize; DWORD dwDummy; BOOL fRedialOnLinkFailure; BOOL fAtLeastOneDeviceAvailable = FALSE; DWORD dwDialMode = RASEDM_DialAll; VOID * pvSubEntryHandlerContext = NULL; VOID * pvSubEntryHandler = NULL; DDM_SUBENTRY_ENUMCONTEXT EnumContext;
EnumContext.pIfObject = pIfObject; EnumContext.fAtLeastOneDeviceAvailable = FALSE; pvSubEntryHandlerContext = &EnumContext; pvSubEntryHandler = (VOID *)IfObjectSubEntryEnumHandler;
dwRetCode = DDMGetPhonebookInfo( gblpRouterPhoneBook, pIfObject->lpwsInterfaceName, &(pIfObject->dwNumSubEntries), &(pIfObject->dwNumOfReConnectAttempts), &(pIfObject->dwSecondsBetweenReConnectAttempts), &fRedialOnLinkFailure, pIfObject->PppInterfaceInfo.szzParameters, &dwDialMode, ppvContext, pvSubEntryHandler, pvSubEntryHandlerContext );
if ( dwRetCode != NO_ERROR ) { return( dwRetCode ); }
if ( fRedialOnLinkFailure ) { pIfObject->fFlags |= IFFLAG_PERSISTENT; } else { pIfObject->fFlags &= ~IFFLAG_PERSISTENT; }
if( RASEDM_DialAsNeeded == dwDialMode) { pIfObject->fFlags |= IFFLAG_DIALMODE_DIALASNEEDED; } else { pIfObject->fFlags &= ~(IFFLAG_DIALMODE_DIALASNEEDED); }
if( RASEDM_DialAll == dwDialMode ) { pIfObject->fFlags |= IFFLAG_DIALMODE_DIALALL; } else { pIfObject->fFlags &= ~(IFFLAG_DIALMODE_DIALALL); }
fAtLeastOneDeviceAvailable = EnumContext.fAtLeastOneDeviceAvailable;
#if 0
else { //
// Iterate through all the subentries - fall back to the
// slow algorithm - we don't have the context
//
for( dwIndex = 1; dwIndex <= pIfObject->dwNumSubEntries; dwIndex++ ) { //
// Get the device type
//
dwSize = 0;
dwRetCode = RasGetSubEntryProperties( gblpRouterPhoneBook, pIfObject->lpwsInterfaceName, dwIndex, NULL, &dwSize, (LPBYTE)&dwDummy, &dwDummy );
if ( dwRetCode != ERROR_BUFFER_TOO_SMALL ) { return ( dwRetCode ); }
pRasSubEntry = LOCAL_ALLOC( LPTR, dwSize ); if ( pRasSubEntry == NULL ) { return ( GetLastError() ); }
ZeroMemory( pRasSubEntry, dwSize ); pRasSubEntry->dwSize = sizeof( RASSUBENTRY );
dwRetCode = RasGetSubEntryProperties( gblpRouterPhoneBook, pIfObject->lpwsInterfaceName, dwIndex, pRasSubEntry, &dwSize, (LPBYTE)&dwDummy, &dwDummy );
if ( dwRetCode != NO_ERROR ) { LOCAL_FREE( pRasSubEntry ); return( dwRetCode ); }
//
// Set the bit for this media
//
dwRetCode = MediaObjSetMediaBit( pRasSubEntry->szDeviceType, &(pIfObject->fMediaUsed) );
LOCAL_FREE( pRasSubEntry );
if ( dwRetCode == NO_ERROR ) { fAtLeastOneDeviceAvailable = TRUE; } } } #endif
if ( !fAtLeastOneDeviceAvailable ) { return( ERROR_INTERFACE_HAS_NO_DEVICES ); }
return( NO_ERROR ); }
//**
//
// Call: IfObjectInitiatePersistentConnections
//
// Returns: None
//
// Description: Will initiate connections for all demand dial interfaces that
// are marked as persistent
//
VOID IfObjectInitiatePersistentConnections( VOID ) { DWORD dwBucketIndex; ROUTER_INTERFACE_OBJECT * pIfObject; DWORD dwRetCode;
EnterCriticalSection( &(gblpInterfaceTable->CriticalSection) );
for ( dwBucketIndex = 0; dwBucketIndex < NUM_IF_BUCKETS; dwBucketIndex++ ) { for( pIfObject = gblpInterfaceTable->IfBucket[dwBucketIndex]; pIfObject != (ROUTER_INTERFACE_OBJECT *)NULL; pIfObject = pIfObject->pNext ) { if ( pIfObject->IfType == ROUTER_IF_TYPE_FULL_ROUTER ) { if ( pIfObject->fFlags & IFFLAG_PERSISTENT ) { dwRetCode = RasConnectionInitiate( pIfObject, FALSE );
DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM, "Initiated persistent connection to %ws,dwRetCode=%d\n", pIfObject->lpwsInterfaceName, dwRetCode );
if ( dwRetCode != NO_ERROR ) { LPWSTR lpwsAudit[1];
lpwsAudit[0] = pIfObject->lpwsInterfaceName;
DDMLogErrorString( ROUTERLOG_PERSISTENT_CONNECTION_FAILURE, 1, lpwsAudit, dwRetCode, 1 ); } } else { //
// Otherwise set dialout hours restrictions, if any
//
IfObjectSetDialoutHoursRestriction( pIfObject ); } } } }
LeaveCriticalSection( &(gblpInterfaceTable->CriticalSection) ); }
//**
//
// Call: IfObjectDisconnectInterfaces
//
// Returns: None
//
// Description: Will disconnect all interfaces that are connected or in the
// process of connecting.
//
VOID IfObjectDisconnectInterfaces( VOID ) { ROUTER_INTERFACE_OBJECT * pIfObject; DWORD dwBucketIndex;
EnterCriticalSection( &(gblpInterfaceTable->CriticalSection) );
for ( dwBucketIndex = 0; dwBucketIndex < NUM_IF_BUCKETS; dwBucketIndex++ ) { for( pIfObject = gblpInterfaceTable->IfBucket[dwBucketIndex]; pIfObject != (ROUTER_INTERFACE_OBJECT *)NULL; pIfObject = pIfObject->pNext ) { if ( ( pIfObject->State != RISTATE_DISCONNECTED ) && ( pIfObject->fFlags & IFFLAG_LOCALLY_INITIATED ) ) { DDM_PRINT( gblDDMConfigInfo.dwTraceId, TRACE_FSM, "IfObjectDisconnectInterfaces: hanging up 0x%x", pIfObject->hRasConn); RasHangUp( pIfObject->hRasConn ); } } }
LeaveCriticalSection( &(gblpInterfaceTable->CriticalSection) ); }
//**
//
// Call: IfObjectConnectionChangeNotification
//
// Returns: NO_ERROR - Success
// Non-zero returns - Failure
//
// Description:
//
VOID IfObjectConnectionChangeNotification( VOID ) { NOTIFICATION_EVENT * pNotificationEvent;
for( pNotificationEvent = (NOTIFICATION_EVENT *) (gblDDMConfigInfo.NotificationEventListHead.Flink); pNotificationEvent != (NOTIFICATION_EVENT *) &(gblDDMConfigInfo.NotificationEventListHead); pNotificationEvent = (NOTIFICATION_EVENT *) (pNotificationEvent->ListEntry.Flink) ) { SetEvent( pNotificationEvent->hEventRouter ); } }
//**
//
// Call: IfObjectSetDialoutHoursRestriction
//
// Returns: NONE
//
// Description: Called from ifapi.c from DIM to initiate dialout hours
// restriction for this interface.
//
VOID IfObjectSetDialoutHoursRestriction( IN ROUTER_INTERFACE_OBJECT * pIfObject ) { TimerQRemove( pIfObject->hDIMInterface, SetDialoutHoursRestriction );
SetDialoutHoursRestriction( pIfObject->hDIMInterface ); }
|