windows-nt/Source/XPSP1/NT/net/rras/dim/server/ifobject.c

802 lines
21 KiB
C
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/********************************************************************/
/** Copyright(c) 1995 Microsoft Corporation. **/
/********************************************************************/
//***
//
// Filename: ifobject.c
//
// Description: Routines to manipulate ROUTER_INTERFACE_OBJECTs
//
// History: May 11,1995 NarenG Created original version.
//
#include "dimsvcp.h"
#include <netconp.h>
//**
//
// Call: GetNewIfHandle
//
// Returns: Handle for new interface
//
// Description: Will generate an id that will be used for an handle to the new
// interface.
//
HANDLE
GetNewIfHandle(
VOID
)
{
static DWORD Id = 2;
return( (HANDLE)UlongToPtr(Id++) );
}
//**
//
// 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 dwInterfaceReachableAfterSecondsMin,
IN DWORD dwInterfaceReachableAfterSecondsMax,
IN LPWSTR lpwsDialoutHoursRestriction
)
{
DWORD dwRetCode;
ROUTER_INTERFACE_OBJECT * pIfObject;
DWORD dwIfObjectSize;
DWORD dwTransportIndex;
//
// On a workstation we do not allow creation of demand-dial interfaces
//
if ( gblDIMConfigInfo.NtProductType == NtProductWinNt )
{
if ( ( IfType == ROUTER_IF_TYPE_FULL_ROUTER ) )
{
WCHAR * pChar = lpwstrName;
DIMLogWarning( ROUTERLOG_LIMITED_WKSTA_SUPPORT,1, &pChar );
SetLastError( ERROR_NOT_SUPPORTED );
return( (ROUTER_INTERFACE_OBJECT *)NULL );
}
}
//
// Hardcode to 2 routermanagers, one for IP, one for IPX. We need to do this
// because then we do not need to reallocate the size to accomodate a new protocol
// when it is added dynamically to the router
//
dwIfObjectSize = sizeof( ROUTER_INTERFACE_OBJECT )
+ ( sizeof( ROUTER_INTERFACE_TRANSPORT ) * 2 );
pIfObject = (ROUTER_INTERFACE_OBJECT *)LOCAL_ALLOC( LPTR, dwIfObjectSize );
if ( pIfObject == (ROUTER_INTERFACE_OBJECT *)NULL )
{
return( (ROUTER_INTERFACE_OBJECT *)NULL );
}
pIfObject->lpwsInterfaceName = (LPWSTR)LOCAL_ALLOC( LPTR,
(wcslen(lpwstrName)+1)
* sizeof(WCHAR) );
if ( pIfObject->lpwsInterfaceName == (LPWSTR)NULL )
{
IfObjectFree( pIfObject );
return( (ROUTER_INTERFACE_OBJECT *)NULL );
}
if ( ( IfType == ROUTER_IF_TYPE_DEDICATED ) ||
( IfType == ROUTER_IF_TYPE_TUNNEL1 ) ||
( IfType == ROUTER_IF_TYPE_INTERNAL ) )
{
if ( !fEnabled )
{
WCHAR * pChar = lpwstrName;
SetLastError( ERROR_INVALID_PARAMETER );
DIMLogErrorString( ROUTERLOG_COULDNT_LOAD_IF, 1, &pChar,
ERROR_INVALID_PARAMETER, 1 );
IfObjectFree( pIfObject );
return( (ROUTER_INTERFACE_OBJECT *)NULL );
}
}
pIfObject->dwReachableAfterSecondsMin=dwInterfaceReachableAfterSecondsMin;
pIfObject->dwReachableAfterSecondsMax=dwInterfaceReachableAfterSecondsMax;
pIfObject->dwReachableAfterSeconds =dwInterfaceReachableAfterSecondsMin;
wcscpy( pIfObject->lpwsInterfaceName, lpwstrName );
pIfObject->State = State;
pIfObject->IfType = IfType;
pIfObject->hConnection = hConnection;
pIfObject->hDIMInterface = ( IfType == ROUTER_IF_TYPE_LOOPBACK )
? (HANDLE)1
: GetNewIfHandle();
pIfObject->fFlags = ( fEnabled ) ? IFFLAG_ENABLED : 0;
pIfObject->hEventNotifyCaller = INVALID_HANDLE_VALUE;
//
// Initialize the router manager handles
//
for ( dwTransportIndex = 0;
dwTransportIndex < gblDIMConfigInfo.dwNumRouterManagers;
dwTransportIndex++ )
{
pIfObject->Transport[dwTransportIndex].hInterface=INVALID_HANDLE_VALUE;
}
//
// If we are running in LANONLYMode then we do not care about media bits
//
if ( gblDIMConfigInfo.dwRouterRole == ROUTER_ROLE_LAN )
{
return( pIfObject );
}
if ( ( IfType == ROUTER_IF_TYPE_FULL_ROUTER ) )
{
DWORD (*IfObjectLoadPhonebookInfo)( ROUTER_INTERFACE_OBJECT * ) =
(DWORD(*)( ROUTER_INTERFACE_OBJECT * ))
GetDDMEntryPoint("IfObjectLoadPhonebookInfo");
//
// Load phonebook information for this interface
//
dwRetCode = IfObjectLoadPhonebookInfo( pIfObject );
if ( dwRetCode != NO_ERROR )
{
if ( dwRetCode == ERROR_INTERFACE_HAS_NO_DEVICES )
{
pIfObject->fFlags |= IFFLAG_OUT_OF_RESOURCES;
}
else
{
WCHAR * pChar = lpwstrName;
DIMLogErrorString( ROUTERLOG_COULDNT_LOAD_IF, 1, &pChar,
dwRetCode, 1 );
SetLastError( dwRetCode );
IfObjectFree( pIfObject );
return( NULL );
}
}
pIfObject->lpwsDialoutHoursRestriction = lpwsDialoutHoursRestriction;
}
return( pIfObject );
}
//**
//
// Call: IfObjectInsertInTable
//
// Returns: NO_ERROR - Success
// ERROR_MAX_WAN_INTERFACE_LIMIT - Failure
// ERROR_MAX_LAN_INTERFACE_LIMIT - Failure
// ERROR_MAX_CLIENT_INTERFACE_LIMIT - Failure
//
// Description: Will insert this interface object into the interface object
// table
//
DWORD
IfObjectInsertInTable(
IN ROUTER_INTERFACE_OBJECT * pIfObject
)
{
DWORD dwBucketIndex=IfObjectHashIfHandleToBucket(pIfObject->hDIMInterface);
if ( pIfObject->IfType == ROUTER_IF_TYPE_FULL_ROUTER )
{
if ( gblInterfaceTable.dwNumWanInterfaces == DIM_MAX_WAN_INTERFACES )
{
return( ERROR_MAX_WAN_INTERFACE_LIMIT );
}
else
{
gblInterfaceTable.dwNumWanInterfaces++;
}
}
else if ( pIfObject->IfType == ROUTER_IF_TYPE_DEDICATED )
{
if ( gblInterfaceTable.dwNumLanInterfaces == DIM_MAX_LAN_INTERFACES )
{
return( ERROR_MAX_LAN_INTERFACE_LIMIT );
}
else
{
gblInterfaceTable.dwNumLanInterfaces++;
}
}
else if ( pIfObject->IfType == ROUTER_IF_TYPE_CLIENT )
{
if (gblInterfaceTable.dwNumClientInterfaces==DIM_MAX_CLIENT_INTERFACES)
{
return( ERROR_MAX_CLIENT_INTERFACE_LIMIT );
}
else
{
gblInterfaceTable.dwNumClientInterfaces++;
}
}
pIfObject->pNext = gblInterfaceTable.IfBucket[dwBucketIndex];
gblInterfaceTable.IfBucket[dwBucketIndex] = pIfObject;
gblInterfaceTable.dwNumTotalInterfaces++;
return( NO_ERROR );
}
//**
//
// Call:
//
// Returns:
//
// Description:
//
ROUTER_INTERFACE_OBJECT *
IfObjectGetPointer(
IN HANDLE hDIMInterface
)
{
DWORD dwBucketIndex;
ROUTER_INTERFACE_OBJECT * pIfObject;
dwBucketIndex = IfObjectHashIfHandleToBucket(hDIMInterface);
for( pIfObject = gblInterfaceTable.IfBucket[dwBucketIndex];
pIfObject != (ROUTER_INTERFACE_OBJECT *)NULL;
pIfObject = pIfObject->pNext )
{
if ( pIfObject->hDIMInterface == hDIMInterface )
{
return( pIfObject );
}
}
return( (ROUTER_INTERFACE_OBJECT *)NULL );
}
//**
//
// Call: IfObjectHashIfHandleToBucket
//
// Returns:
//
// Description:
//
DWORD
IfObjectHashIfHandleToBucket(
IN HANDLE hDIMInterface
)
{
return( (DWORD)((ULONG_PTR)hDIMInterface) % NUM_IF_BUCKETS );
}
//**
//
// Call: IfObjectRemove
//
// Returns:
//
// Description:
//
VOID
IfObjectRemove(
IN HANDLE hDIMInterface
)
{
DWORD dwBucketIndex;
ROUTER_INTERFACE_OBJECT * pIfObject;
ROUTER_INTERFACE_OBJECT * pIfObjectPrev;
dwBucketIndex = IfObjectHashIfHandleToBucket(hDIMInterface);
pIfObject = gblInterfaceTable.IfBucket[dwBucketIndex];
pIfObjectPrev = pIfObject;
while( pIfObject != (ROUTER_INTERFACE_OBJECT *)NULL )
{
if ( pIfObject->hDIMInterface == hDIMInterface )
{
if ( gblInterfaceTable.IfBucket[dwBucketIndex] == pIfObject )
{
gblInterfaceTable.IfBucket[dwBucketIndex] = pIfObject->pNext;
}
else
{
pIfObjectPrev->pNext = pIfObject->pNext;
}
gblInterfaceTable.dwNumTotalInterfaces--;
if ( pIfObject->IfType == ROUTER_IF_TYPE_FULL_ROUTER )
{
gblInterfaceTable.dwNumWanInterfaces--;
}
else if ( pIfObject->IfType == ROUTER_IF_TYPE_DEDICATED )
{
gblInterfaceTable.dwNumLanInterfaces--;
}
else if ( pIfObject->IfType == ROUTER_IF_TYPE_CLIENT )
{
gblInterfaceTable.dwNumClientInterfaces--;
}
IfObjectFree( pIfObject );
return;
}
pIfObjectPrev = pIfObject;
pIfObject = pIfObject->pNext;
}
}
//**
//
// Call: IfObjectFree
//
// Returns: NO_ERROR - Success
// Non-zero returns - Failure
//
// Description: Will release all memory allocated for the interfae object.
//
VOID
IfObjectFree(
IN ROUTER_INTERFACE_OBJECT * pIfObject
)
{
if ( pIfObject->lpwsInterfaceName != NULL )
{
LOCAL_FREE( pIfObject->lpwsInterfaceName );
}
if ( pIfObject->lpwsDialoutHoursRestriction != NULL )
{
LOCAL_FREE( pIfObject->lpwsDialoutHoursRestriction );
}
LOCAL_FREE( pIfObject );
}
//**
//
// Call: IfObjectGetPointerByName
//
// Returns:
//
// Description:
//
ROUTER_INTERFACE_OBJECT *
IfObjectGetPointerByName(
IN LPWSTR lpwstrName,
IN BOOL fIncludeClientInterfaces
)
{
DWORD dwBucketIndex;
ROUTER_INTERFACE_OBJECT * pIfObject;
for ( dwBucketIndex = 0; dwBucketIndex < NUM_IF_BUCKETS; dwBucketIndex++ )
{
for( pIfObject = gblInterfaceTable.IfBucket[dwBucketIndex];
pIfObject != (ROUTER_INTERFACE_OBJECT *)NULL;
pIfObject = pIfObject->pNext )
{
if ( _wcsicmp( pIfObject->lpwsInterfaceName, lpwstrName ) == 0 )
{
if ( pIfObject->IfType == ROUTER_IF_TYPE_CLIENT )
{
if ( fIncludeClientInterfaces )
{
return( pIfObject );
}
else
{
continue;
}
}
return( pIfObject );
}
}
}
return( (ROUTER_INTERFACE_OBJECT *)NULL );
}
//**
//
// Call: IfObjectDoesLanInterfaceExist
//
// Returns: NO_ERROR - Success
// Non-zero returns - Failure
//
// Description:
//
BOOL
IfObjectDoesLanInterfaceExist(
VOID
)
{
DWORD dwBucketIndex;
ROUTER_INTERFACE_OBJECT * pIfObject;
for ( dwBucketIndex = 0; dwBucketIndex < NUM_IF_BUCKETS; dwBucketIndex++ )
{
for( pIfObject = gblInterfaceTable.IfBucket[dwBucketIndex];
pIfObject != (ROUTER_INTERFACE_OBJECT *)NULL;
pIfObject = pIfObject->pNext )
{
if ( pIfObject->IfType == ROUTER_IF_TYPE_DEDICATED )
{
return( TRUE );
}
}
}
return( FALSE );
}
//**
//
// Call: IfObjectWANDeviceInstalled
//
// Returns: None
//
// Description: Called by DDM whenever a WAN device is installed or removed
//
VOID
IfObjectWANDeviceInstalled(
IN BOOL fWANDeviceInstalled
)
{
DWORD dwXportIndex = GetTransportIndex( PID_IP );
//
// If a WAN device is installed and IP is installed then we
// start advertizing on specific multicast address so as to make this
// router discoverable
//
if ( ( fWANDeviceInstalled ) && ( dwXportIndex != (DWORD)-1 ) )
{
DWORD dwRetCode =
gblRouterManagers[dwXportIndex].DdmRouterIf.SetRasAdvEnable(
fWANDeviceInstalled );
DIMTRACE2( "Calling SetRasAdvEnable( %d ) = %d",
fWANDeviceInstalled, dwRetCode );
}
}
//**
//
// Call: IfObjectNotifyOfMediaSenseChange
//
// Returns: None
//
// Description: Notifies the object of change in reachablity status due to
// media sense.
//
//
VOID
IfObjectNotifyOfMediaSenseChange(
VOID
)
{
DWORD dwBucketIndex;
ROUTER_INTERFACE_OBJECT * pIfObject;
EnterCriticalSection( &(gblInterfaceTable.CriticalSection) );
for ( dwBucketIndex = 0; dwBucketIndex < NUM_IF_BUCKETS; dwBucketIndex++ )
{
for( pIfObject = gblInterfaceTable.IfBucket[dwBucketIndex];
pIfObject != (ROUTER_INTERFACE_OBJECT *)NULL;
pIfObject = pIfObject->pNext )
{
if ( pIfObject->IfType == ROUTER_IF_TYPE_DEDICATED )
{
DWORD dwInactiveReason;
if ( IfObjectIsLANDeviceActive( pIfObject->lpwsInterfaceName,
&dwInactiveReason ) )
{
if ( pIfObject->State != RISTATE_CONNECTED )
{
pIfObject->State = RISTATE_CONNECTED;
pIfObject->fFlags &= ~IFFLAG_NO_MEDIA_SENSE;
IfObjectNotifyOfReachabilityChange(
pIfObject,
TRUE,
INTERFACE_NO_MEDIA_SENSE );
}
}
else if ( dwInactiveReason == INTERFACE_NO_MEDIA_SENSE )
{
if ( pIfObject->State != RISTATE_DISCONNECTED )
{
pIfObject->State = RISTATE_DISCONNECTED;
pIfObject->fFlags |= IFFLAG_NO_MEDIA_SENSE;
IfObjectNotifyOfReachabilityChange(
pIfObject,
FALSE,
INTERFACE_NO_MEDIA_SENSE );
}
}
}
}
}
LeaveCriticalSection( &(gblInterfaceTable.CriticalSection) );
}
//**
//
// Call: IfObjectNotifyOfReachabilityChange
//
// Returns: None
//
// Description: Notifies the object of change in reachablity status due to
// media sense.
//
//
VOID
IfObjectNotifyOfReachabilityChange(
IN ROUTER_INTERFACE_OBJECT * pIfObject,
IN BOOL fReachable,
IN UNREACHABILITY_REASON dwReason
)
{
DWORD dwIndex;
WCHAR wchFriendlyName[MAX_INTERFACE_NAME_LEN+1];
LPWSTR lpszFriendlyName = wchFriendlyName;
for ( dwIndex = 0;
dwIndex < gblDIMConfigInfo.dwNumRouterManagers;
dwIndex++ )
{
if ( pIfObject->Transport[dwIndex].hInterface == INVALID_HANDLE_VALUE )
{
continue;
}
if ( fReachable )
{
DIMTRACE2( "Notifying Protocol = 0x%x, Interface=%ws is Reachable",
gblRouterManagers[dwIndex].DdmRouterIf.dwProtocolId,
pIfObject->lpwsInterfaceName );
gblRouterManagers[dwIndex].DdmRouterIf.InterfaceReachable(
pIfObject->Transport[dwIndex].hInterface );
}
else
{
DIMTRACE3(
"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 ( MprConfigGetFriendlyName( gblDIMConfigInfo.hMprConfig,
pIfObject->lpwsInterfaceName,
wchFriendlyName,
sizeof( wchFriendlyName ) ) != NO_ERROR )
{
wcscpy( wchFriendlyName, pIfObject->lpwsInterfaceName );
}
if ( fReachable )
{
DIMLogInformation(ROUTERLOG_IF_REACHABLE,1, &lpszFriendlyName );
}
else
{
DWORD dwEventLogId = 0;
switch( dwReason )
{
case INTERFACE_OUT_OF_RESOURCES:
dwEventLogId = ROUTERLOG_IF_UNREACHABLE_REASON1;
break;
case INTERFACE_CONNECTION_FAILURE:
dwEventLogId = ROUTERLOG_IF_UNREACHABLE_REASON2;
break;
case INTERFACE_DISABLED:
dwEventLogId = ROUTERLOG_IF_UNREACHABLE_REASON3;
break;
case INTERFACE_SERVICE_IS_PAUSED:
dwEventLogId = ROUTERLOG_IF_UNREACHABLE_REASON4;
break;
case INTERFACE_DIALOUT_HOURS_RESTRICTION:
dwEventLogId = ROUTERLOG_IF_UNREACHABLE_REASON5;
break;
case INTERFACE_NO_MEDIA_SENSE:
dwEventLogId = ROUTERLOG_IF_UNREACHABLE_REASON6;
break;
case INTERFACE_NO_DEVICE:
dwEventLogId = ROUTERLOG_IF_UNREACHABLE_REASON7;
break;
default:
dwEventLogId = 0;
break;
}
if ( dwEventLogId != 0 )
{
DIMLogInformation( dwEventLogId, 1, &lpszFriendlyName );
}
}
}
//**
//
// Call: IfObjectIsLANDeviceActive
//
// Returns: NO_ERROR - Success
// Non-zero returns - Failure
//
// Description:
//
BOOL
IfObjectIsLANDeviceActive(
IN LPWSTR lpwsInterfaceName,
OUT LPDWORD lpdwInactiveReason
)
{
NETCON_STATUS NetConStatus;
HRESULT hResult;
BOOL fEnabled;
GUID Guid;
NTSTATUS NtStatus;
UNICODE_STRING usTemp;
//
// First check media state
//
usTemp.Length = wcslen(lpwsInterfaceName) * sizeof(WCHAR);
usTemp.MaximumLength = usTemp.Length + sizeof(WCHAR);
usTemp.Buffer = lpwsInterfaceName;
NtStatus = RtlGUIDFromString( &usTemp, &Guid );
if ( NtStatus != STATUS_SUCCESS )
{
*lpdwInactiveReason = INTERFACE_NO_DEVICE;
return( FALSE );
}
hResult = HrGetPnpDeviceStatus( &Guid, &NetConStatus );
if ( HRESULT_CODE( hResult ) == NO_ERROR )
{
switch ( NetConStatus )
{
case NCS_MEDIA_DISCONNECTED:
*lpdwInactiveReason = INTERFACE_NO_MEDIA_SENSE;
return( FALSE );
case NCS_CONNECTED:
case NCS_INVALID_ADDRESS:
case NCS_AUTHENTICATING:
case NCS_CREDENTIALS_REQUIRED:
case NCS_AUTHENTICATION_FAILED:
case NCS_AUTHENTICATION_SUCCEEDED:
{
return( TRUE );
}
default:
*lpdwInactiveReason = INTERFACE_NO_DEVICE;
return( FALSE );
}
}
else
{
*lpdwInactiveReason = INTERFACE_NO_DEVICE;
return( FALSE );
}
return( TRUE );
}
//**
//
// Call: IfObjectDeleteInterface
//
// Returns: None
//
// Description: Delete this interface with all the router managers.
//
//
VOID
IfObjectDeleteInterfaceFromTransport(
IN ROUTER_INTERFACE_OBJECT * pIfObject,
IN DWORD dwPid
)
{
DWORD dwIndex;
DIM_ROUTER_INTERFACE * pDdmRouterIf;
DWORD dwRetCode;
for ( dwIndex = 0;
dwIndex < gblDIMConfigInfo.dwNumRouterManagers;
dwIndex++ )
{
if ( pIfObject->Transport[dwIndex].hInterface == INVALID_HANDLE_VALUE )
{
continue;
}
pDdmRouterIf=&(gblRouterManagers[dwIndex].DdmRouterIf);
if ( pDdmRouterIf->dwProtocolId == dwPid )
{
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";
DIMLogErrorString( ROUTERLOG_COULDNT_REMOVE_INTERFACE, 2,
lpwsInsertStrings, dwRetCode, 2 );
}
pIfObject->Transport[dwIndex].hInterface = INVALID_HANDLE_VALUE;
}
}
}