Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

716 lines
12 KiB

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