/*++ Copyright (c) 1995 Microsoft Corporation Module Name: net\routing\ip\rtrmgr\map.c Abstract: Utility functions for various lookups and mappings Revision History: Amritansh Raghav 10/6/95 Created --*/ #include "allinc.h" VOID InitHashTables( VOID ) /*++ Routine Description This function initializes the various mapping tables Locks None. Called at init time Arguments None Return Value None --*/ { DWORD i; TraceEnter("InitHashTables"); /* for(i = 0; i < ADAPTER_HASH_TABLE_SIZE; i++) { InitializeListHead(&(g_rgleAdapterMapTable[i])); } */ for(i = 0; i < BINDING_HASH_TABLE_SIZE; i++) { InitializeListHead(&g_leBindingTable[i]); } g_ulNumBindings = 0; TraceLeave("InitHashTables"); } VOID UnInitHashTables( VOID ) /*++ Routine Description Undo whatever was done in InitHasTables() Locks None Arguments None Return Value None --*/ { DWORD i; PLIST_ENTRY pleHead; PLIST_ENTRY pleNode; TraceEnter("UnInitHashTables"); /* for(i = 0; i < ADAPTER_HASH_TABLE_SIZE; i++) { pleHead = &g_rgleAdapterMapTable[i]; while(!IsListEmpty(pleHead)) { PADAPTER_MAP pAIBlock; pleNode = RemoveHeadList(pleHead); pAIBlock = CONTAINING_RECORD(pleNode,ADAPTER_MAP,leHashLink); HeapFree(GetProcessHeap(),0,pAIBlock); } } */ for(i = 0; i < BINDING_HASH_TABLE_SIZE; i++) { pleHead = &g_leBindingTable[i]; while(!IsListEmpty(pleHead)) { PADAPTER_INFO pBinding; pleNode = RemoveHeadList(pleHead); pBinding = CONTAINING_RECORD(pleNode, ADAPTER_INFO, leHashLink); Trace1(ERR, "UnInitHashTables: Binding found for %d", pBinding->dwIfIndex); HeapFree(IPRouterHeap, 0, pBinding); } } g_ulNumBindings = 0; TraceLeave("UnInitHashTables"); } VOID AddBinding( PICB picb ) /*++ Routine Description Adds a binding info node to the hash table. Increments the g_ulNumBindings to track the number of addresses on the system Locks ICB lock as writer BINDING lock as writer Arguments picb The ICB of the interface whose bindings need to be added to the binding list. Return Value None --*/ { PADAPTER_INFO pBinding; DWORD i, dwNumAddr; #if DBG PLIST_ENTRY pleNode; #endif IpRtAssert(picb->pibBindings isnot NULL); IpRtAssert(picb->bBound); // // adapter info always has space for one address/mask. This is needed // for the address table // dwNumAddr = picb->dwNumAddresses ? picb->dwNumAddresses : 1; pBinding = HeapAlloc(IPRouterHeap, HEAP_ZERO_MEMORY, SIZEOF_ADAPTER_INFO(picb->dwNumAddresses)); if(pBinding is NULL) { Trace1(ERR, "AddBinding: Error %d allocating memory", GetLastError()); IpRtAssert(FALSE); return; } pBinding->pInterfaceCB = picb; pBinding->bBound = picb->bBound; pBinding->dwIfIndex = picb->dwIfIndex; pBinding->dwNumAddresses = picb->dwNumAddresses; pBinding->dwRemoteAddress = picb->dwRemoteAddress; pBinding->dwBCastBit = picb->dwBCastBit; pBinding->dwReassemblySize = picb->dwReassemblySize; pBinding->ritType = picb->ritType; for(i = 0; i < picb->dwNumAddresses; i++) { // // structure assignment // pBinding->rgibBinding[i] = picb->pibBindings[i]; } #if DBG for(pleNode = g_leBindingTable[BIND_HASH(picb->dwIfIndex)].Flink; pleNode isnot &g_leBindingTable[BIND_HASH(picb->dwIfIndex)]; pleNode = pleNode->Flink) { PADAPTER_INFO pTempBind; pTempBind = CONTAINING_RECORD(pleNode, ADAPTER_INFO, leHashLink); IpRtAssert(pTempBind->dwIfIndex isnot picb->dwIfIndex); } #endif InsertHeadList(&g_leBindingTable[BIND_HASH(picb->dwIfIndex)], &(pBinding->leHashLink)); g_ulNumBindings += (picb->dwNumAddresses ? picb->dwNumAddresses : 1); g_LastUpdateTable[IPADDRCACHE] = 0; return; } VOID RemoveBinding( PICB picb ) /*++ Routine Description Called to remove the bindings associated with an interface Locks ICB lock held as WRITER BINDING list lock held as WRITER Arguments picb ICB of the interface whose bindings need to be removed Return Value None --*/ { PADAPTER_INFO pBind; pBind = GetInterfaceBinding(picb->dwIfIndex); if(pBind isnot NULL) { RemoveEntryList(&(pBind->leHashLink)); g_ulNumBindings -= (pBind->dwNumAddresses? pBind->dwNumAddresses : 1); HeapFree(IPRouterHeap, 0, pBind); g_LastUpdateTable[IPADDRCACHE] = 0; return; } Trace0(ERR, "RemoveBinding: BINDING NOT FOUND"); IpRtAssert(FALSE); } PADAPTER_INFO GetInterfaceBinding( DWORD dwIfIndex ) /*++ Routine Description Retrieves a pointer to the binding info from hash table Locks BINDING lock held atleast as READER Arguments dwIfIndex Interface Index for the interface whose bindings need to be looked up Return Value Pointer to binding information if the binding was found NULL if binding was not found --*/ { PLIST_ENTRY pleNode; PADAPTER_INFO pBinding; for(pleNode = g_leBindingTable[BIND_HASH(dwIfIndex)].Flink; pleNode isnot &g_leBindingTable[BIND_HASH(dwIfIndex)]; pleNode = pleNode->Flink) { pBinding = CONTAINING_RECORD(pleNode,ADAPTER_INFO,leHashLink); if(pBinding->dwIfIndex is dwIfIndex) { return pBinding; } } Trace0(ERR, "GetInterfaceBinding: BINDING NOT FOUND"); return NULL; } #if DBG VOID CheckBindingConsistency( PICB picb ) /*++ Routine Description This Locks None Arguments None Return Value None --*/ { } #endif // // The following are the set of various mapping functions // They require that you already possess the dwLock before you call them // #if 0 DWORD StoreAdapterToInterfaceMap( DWORD dwAdapterId, DWORD dwIfIndex ) { PADAPTER_MAP pAIBlock; if((pAIBlock = LookUpAdapterHash(dwAdapterId)) isnot NULL) { pAIBlock->dwIfIndex = dwIfIndex; return NO_ERROR; } // // Wasnt found // if((pAIBlock = HeapAlloc(GetProcessHeap(),0,sizeof(ADAPTER_MAP))) is NULL) { return ERROR_NOT_ENOUGH_MEMORY; } pAIBlock->dwAdapterId = dwAdapterId; pAIBlock->dwIfIndex = dwIfIndex; InsertAdapterHash(pAIBlock); return NO_ERROR; } DWORD DeleteAdapterToInterfaceMap( DWORD dwAdapterId ) { PADAPTER_MAP pAIBlock; if((pAIBlock = LookUpAdapterHash(dwAdapterId)) isnot NULL) { pAIBlock->dwIfIndex = INVALID_IF_INDEX; return NO_ERROR; } return INVALID_ADAPTER_ID; } DWORD GetInterfaceFromAdapter( DWORD dwAdapterId ) { PADAPTER_MAP pAIBlock; if((pAIBlock = LookUpAdapterHash(dwAdapterId)) isnot NULL) { return pAIBlock->dwIfIndex; } return INVALID_ADAPTER_ID; } PADAPTER_MAP LookUpAdapterHash( DWORD dwAdapterId ) { DWORD dwHashIndex; PADAPTER_MAP pAIBlock; PLIST_ENTRY pleCurrent; dwHashIndex = ADAPTER_HASH(dwAdapterId); // // The list is not ordered, travel the whole hash bucket // for(pleCurrent = g_rgleAdapterMapTable[dwHashIndex].Flink; pleCurrent isnot &g_rgleAdapterMapTable[dwHashIndex]; pleCurrent = pleCurrent->Flink) { pAIBlock = CONTAINING_RECORD(pleCurrent,ADAPTER_MAP,leHashLink); if(pAIBlock->dwAdapterId is dwAdapterId) { return pAIBlock; } } return NULL; } VOID InsertAdapterHash( PADAPTER_MAP paiBlock ) { DWORD dwHashIndex; dwHashIndex = ADAPTER_HASH(paiBlock->dwAdapterId); InsertHeadList(&g_rgleAdapterMapTable[dwHashIndex], &paiBlock->leHashLink); } DWORD GetAdapterFromInterface( DWORD dwIfIndex ) { PICB picb; picb = InterfaceLookupByIfIndex(dwIfIndex); CheckBindingConsistency(picb); if(!picb) { Trace0(ERR, "GetAdapterFromInterface: Unable to map interface to adapter since the interface id was not found!"); return INVALID_IF_INDEX; } if((picb->dwOperationalState is CONNECTED) or (picb->dwOperationalState is OPERATIONAL)) { return picb->dwAdapterId; } Trace1(IF, "GetAdapterFromInterface: Unable to map interface to adapter since its operational state was %d", picb->dwOperationalState); return INVALID_IF_INDEX; } #endif // AddInterfaceLookup() // // Function: Adds the given interface to the hash table used for quick look up given // an interface id. // // Returns: Nothing // VOID AddInterfaceLookup( PICB picb ) { PLIST_ENTRY ple; PICB pIcbHash; InsertHeadList(&ICBHashLookup[picb->dwIfIndex % ICB_HASH_TABLE_SIZE], &picb->leHashLink); for ( ple = ICBSeqNumLookup[picb->dwSeqNumber % ICB_HASH_TABLE_SIZE].Flink; ple != &ICBSeqNumLookup[picb->dwSeqNumber % ICB_HASH_TABLE_SIZE]; ple = ple->Flink ) { pIcbHash = CONTAINING_RECORD(ple, ICB, leICBHashLink ); if (pIcbHash->dwSeqNumber > picb->dwSeqNumber) { break; } } InsertTailList(ple, &picb->leICBHashLink); } // RemoveInterfaceLookup() // // Function: Removes the given interface from the hash table used for quick look up given // an interface id. // // Returns: Nothing // VOID RemoveInterfaceLookup( PICB picb ) { RemoveEntryList(&picb->leHashLink); picb->leHashLink.Flink = NULL; picb->leHashLink.Blink = NULL; RemoveEntryList(&picb->leICBHashLink); InitializeListHead(&picb->leICBHashLink); } // InterfaceLookupByICBSeqNumber() // // Function: Returns a pointer to ICB given the sequence number // // Returns: PICB if found - NULL otherwise. // PICB InterfaceLookupByICBSeqNumber( DWORD dwSeqNumber ) { PICB picb; PLIST_ENTRY pleNode; for(pleNode = ICBSeqNumLookup[dwSeqNumber % ICB_HASH_TABLE_SIZE].Flink; pleNode isnot &ICBSeqNumLookup[dwSeqNumber % ICB_HASH_TABLE_SIZE]; pleNode = pleNode->Flink) { picb = CONTAINING_RECORD(pleNode, ICB, leICBHashLink); if (picb->dwSeqNumber < dwSeqNumber) { continue; } if (picb->dwSeqNumber == dwSeqNumber) { return picb; } else { break; } } return NULL; } // // InterfaceLookupByIfIndex() // // Function: Returns a pointer to ICB given the interfaceid // // Returns: PICB if found - NULL otherwise. // PICB InterfaceLookupByIfIndex( DWORD dwIfIndex ) { PICB picb; PLIST_ENTRY pleNode; for(pleNode = ICBHashLookup[dwIfIndex % ICB_HASH_TABLE_SIZE].Flink; pleNode isnot &ICBHashLookup[dwIfIndex % ICB_HASH_TABLE_SIZE]; pleNode = pleNode->Flink) { picb = CONTAINING_RECORD(pleNode, ICB, leHashLink); if (picb->dwIfIndex is dwIfIndex) { return picb; } } return NULL; } DWORD MapInterfaceToAdapter( DWORD Index ) { return Index; #if 0 ENTER_READER(ICB_LIST); Index = GetAdapterFromInterface(Index); EXIT_LOCK(ICB_LIST); return Index; #endif } DWORD MapInterfaceToRouterIfType( DWORD Index ) { DWORD dwIfType = ROUTER_IF_TYPE_INTERNAL; PICB picb; ENTER_READER(ICB_LIST); picb = InterfaceLookupByIfIndex(Index); if (picb) { dwIfType = picb->ritType; } EXIT_LOCK(ICB_LIST); return dwIfType; } DWORD MapAddressToAdapter( DWORD Address ) { DWORD dwAdapterId; DWORD dwBCastBit; DWORD dwReassemblySize; if (GetAdapterInfo(Address, &dwAdapterId, &dwBCastBit, &dwReassemblySize)) { return INVALID_IF_INDEX; } return dwAdapterId; }