/********************************************************************/ /** 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 //** // // 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; } } }