717 lines
12 KiB
C
717 lines
12 KiB
C
/*++
|
|
|
|
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;
|
|
}
|
|
|