361 lines
10 KiB
C
361 lines
10 KiB
C
/*
|
|
File NicTable.c
|
|
|
|
Implements a nic-renaming scheme that allows adaptif to
|
|
advertise whatever nic id it chooses to its clients while
|
|
maintaining the list of actual nic id's internally.
|
|
|
|
This functionality was needed in order to Pnp enable the
|
|
ipx router. When an adapter is deleted, the stack renumbers
|
|
the nicid's so that it maintains a contiguous block of ids
|
|
internally. Rather that cause the clients to adptif to
|
|
match the stack's renumbering schemes, we handle this
|
|
transparently in adptif.
|
|
|
|
Author: Paul Mayfield, 12/11/97
|
|
*/
|
|
|
|
#include "ipxdefs.h"
|
|
|
|
#define NicMapDefaultSize 500
|
|
#define NicMapDefaultFactor 5
|
|
#define MAXIMUM_NIC_MAP_SIZE 25000
|
|
|
|
// Nic map used to associate nic's with virtual ids
|
|
typedef struct _NICMAPNODE {
|
|
USHORT usVirtualId;
|
|
IPX_NIC_INFO * pNicInfo;
|
|
} NICMAPNODE;
|
|
|
|
// Maintains the mapping from nic id to virtual id.
|
|
typedef struct _NICMAP {
|
|
DWORD dwMapSize;
|
|
DWORD dwNicCount;
|
|
DWORD dwMaxNicId;
|
|
NICMAPNODE ** ppNics;
|
|
USHORT * usVirtMap;
|
|
} NICMAP;
|
|
|
|
// Definition of the global nic id map
|
|
NICMAP GlobalNicIdMap;
|
|
|
|
DWORD nmAddNic (NICMAP * pNicMap, IPX_NIC_INFO * pNicInfo);
|
|
|
|
|
|
// Resizes the nic map to accomodate more nics. This function will
|
|
// probably only ever be called to allocate the array the first time.
|
|
DWORD nmEnlarge(NICMAP * pNicMap) {
|
|
USHORT * usVirtMap;
|
|
DWORD i, dwNewSize;
|
|
NICMAPNODE ** ppNics;
|
|
|
|
// Are we enlarging for the first time?
|
|
if (!pNicMap->dwMapSize)
|
|
dwNewSize = NicMapDefaultSize;
|
|
else
|
|
dwNewSize = pNicMap->dwMapSize * NicMapDefaultFactor;
|
|
|
|
// Make sure we aren't too big...
|
|
if (dwNewSize > MAXIMUM_NIC_MAP_SIZE) {
|
|
// do something critical here!
|
|
return ERROR_INSUFFICIENT_BUFFER;
|
|
}
|
|
|
|
// Resize the arrays
|
|
usVirtMap = (USHORT*) RtlAllocateHeap(RtlProcessHeap(),
|
|
0,
|
|
dwNewSize * sizeof(USHORT));
|
|
|
|
ppNics = (NICMAPNODE **) RtlAllocateHeap(RtlProcessHeap(),
|
|
0,
|
|
dwNewSize * sizeof(NICMAPNODE*));
|
|
|
|
if (!usVirtMap || !ppNics)
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
// Initialize
|
|
FillMemory(usVirtMap, dwNewSize * sizeof(USHORT), 0xff);
|
|
ZeroMemory(ppNics, dwNewSize * sizeof(IPX_NIC_INFO*));
|
|
usVirtMap[0] = 0;
|
|
|
|
// Initialize the arrays.
|
|
for (i = 0; i < pNicMap->dwMapSize; i++) {
|
|
usVirtMap[i] = pNicMap->usVirtMap[i];
|
|
ppNics[i] = pNicMap->ppNics[i];
|
|
}
|
|
|
|
// Free old data if needed
|
|
if (pNicMap->dwMapSize) {
|
|
RtlFreeHeap(RtlProcessHeap(), 0, pNicMap->usVirtMap);
|
|
RtlFreeHeap(RtlProcessHeap(), 0, pNicMap->ppNics);
|
|
}
|
|
|
|
// Assign the new arrays
|
|
pNicMap->usVirtMap = usVirtMap;
|
|
pNicMap->ppNics = ppNics;
|
|
pNicMap->dwMapSize = dwNewSize;
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
// Returns the next available nic id
|
|
USHORT nmGetNextVirtualNicId(NICMAP * pNicMap, USHORT usPhysId) {
|
|
DWORD i;
|
|
|
|
// If this can be a one->one mapping, make it so
|
|
if (pNicMap->usVirtMap[usPhysId] == NIC_MAP_INVALID_NICID)
|
|
return usPhysId;
|
|
|
|
// Otherwise, walk the array until you find free spot
|
|
for (i = 2; i < pNicMap->dwMapSize; i++) {
|
|
if (pNicMap->usVirtMap[i] == NIC_MAP_INVALID_NICID)
|
|
return (USHORT)i;
|
|
}
|
|
|
|
return NIC_MAP_INVALID_NICID;
|
|
}
|
|
|
|
// Cleans up the nic
|
|
DWORD nmCleanup (NICMAP * pNicMap) {
|
|
DWORD i;
|
|
|
|
// Cleanup the virtual map
|
|
if (pNicMap->usVirtMap)
|
|
RtlFreeHeap(RtlProcessHeap(), 0, pNicMap->usVirtMap);
|
|
|
|
// Cleanup any of the nics stored in the map
|
|
if (pNicMap->ppNics) {
|
|
for (i = 0; i < pNicMap->dwMapSize; i++) {
|
|
if (pNicMap->ppNics[i]) {
|
|
if (pNicMap->ppNics[i]->pNicInfo)
|
|
RtlFreeHeap(RtlProcessHeap(), 0, pNicMap->ppNics[i]->pNicInfo);
|
|
RtlFreeHeap(RtlProcessHeap(), 0, pNicMap->ppNics[i]);
|
|
}
|
|
}
|
|
RtlFreeHeap(RtlProcessHeap(), 0, pNicMap->ppNics);
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
// Initializes the nic
|
|
DWORD nmInitialize (NICMAP * pNicMap) {
|
|
DWORD dwErr;
|
|
|
|
__try {
|
|
// Enlarge the map to its default size
|
|
ZeroMemory(pNicMap, sizeof (NICMAP));
|
|
if ((dwErr = nmEnlarge(pNicMap)) != NO_ERROR)
|
|
return dwErr;
|
|
}
|
|
__finally {
|
|
if (dwErr != NO_ERROR) {
|
|
nmCleanup(pNicMap);
|
|
pNicMap->dwMapSize = 0;
|
|
}
|
|
}
|
|
|
|
return NO_ERROR;
|
|
|
|
}
|
|
|
|
// Maps virtual nic ids to physical ones
|
|
USHORT nmGetPhysicalId (NICMAP * pNicMap, USHORT usVirtAdp) {
|
|
return pNicMap->usVirtMap[usVirtAdp];
|
|
}
|
|
|
|
// Maps physical nic ids to virtual ones
|
|
USHORT nmGetVirtualId (NICMAP * pNicMap, USHORT usPhysAdp) {
|
|
if (usPhysAdp == NIC_MAP_INVALID_NICID)
|
|
{
|
|
return NIC_MAP_INVALID_NICID;
|
|
}
|
|
if (pNicMap->ppNics[usPhysAdp])
|
|
return pNicMap->ppNics[usPhysAdp]->usVirtualId;
|
|
return (usPhysAdp == 0) ? 0 : NIC_MAP_INVALID_NICID;
|
|
}
|
|
|
|
// Gets the nic info associated with a physical adapter
|
|
IPX_NIC_INFO * nmGetNicInfo (NICMAP * pNicMap, USHORT usPhysAdp) {
|
|
if (pNicMap->ppNics[usPhysAdp])
|
|
return pNicMap->ppNics[usPhysAdp]->pNicInfo;
|
|
return NULL;
|
|
}
|
|
|
|
// Returns the number of nics in the map
|
|
DWORD nmGetNicCount (NICMAP * pNicMap) {
|
|
return pNicMap->dwNicCount;
|
|
}
|
|
|
|
// Returns the current maximum nic id
|
|
DWORD nmGetMaxNicId (NICMAP * pNicMap) {
|
|
return pNicMap->dwMaxNicId;
|
|
}
|
|
|
|
// Reconfigures a nic
|
|
DWORD nmReconfigure(NICMAP * pNicMap, IPX_NIC_INFO * pSrc) {
|
|
IPX_NIC_INFO * pDst = nmGetNicInfo (pNicMap, pSrc->Details.NicId);
|
|
|
|
if (pDst) {
|
|
CopyMemory(pDst, pSrc, sizeof (IPX_NIC_INFO));
|
|
pDst->Details.NicId = nmGetVirtualId (pNicMap, pSrc->Details.NicId);
|
|
}
|
|
else
|
|
return nmAddNic(pNicMap, pSrc);
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
// Adds a nic to the table
|
|
DWORD nmAddNic (NICMAP * pNicMap, IPX_NIC_INFO * pNicInfo) {
|
|
USHORT i = pNicInfo->Details.NicId, usVirt;
|
|
|
|
// If the nic already exists, reconfigure it
|
|
if (pNicMap->ppNics[i])
|
|
return nmReconfigure (pNicMap, pNicInfo);
|
|
|
|
// Otherwise, add it
|
|
pNicMap->ppNics[i] = (NICMAPNODE*) RtlAllocateHeap (RtlProcessHeap(),
|
|
0,
|
|
(sizeof (NICMAPNODE)));
|
|
if (!pNicMap->ppNics[i])
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
pNicMap->ppNics[i]->pNicInfo = (IPX_NIC_INFO *)
|
|
RtlAllocateHeap (RtlProcessHeap(),
|
|
0,
|
|
sizeof (IPX_NIC_INFO));
|
|
if (!pNicMap->ppNics[i]->pNicInfo)
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
|
|
// Initialize it
|
|
usVirt = nmGetNextVirtualNicId(pNicMap, i);
|
|
pNicMap->ppNics[i]->usVirtualId = usVirt;
|
|
pNicMap->ppNics[i]->pNicInfo->Details.NicId = usVirt;
|
|
CopyMemory(pNicMap->ppNics[i]->pNicInfo, pNicInfo, sizeof (IPX_NIC_INFO));
|
|
pNicMap->usVirtMap[usVirt] = i;
|
|
|
|
// Update the nic count and maximum nic id
|
|
if (i > pNicMap->dwMaxNicId)
|
|
pNicMap->dwMaxNicId = i;
|
|
pNicMap->dwNicCount++;
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
// Deletes a nic from the table
|
|
DWORD nmDelNic (NICMAP * pNicMap, IPX_NIC_INFO * pNicInfo) {
|
|
USHORT i = pNicInfo->Details.NicId, usVirt;
|
|
|
|
// If the nic doesn't exists do nothing
|
|
if (! pNicMap->ppNics[i])
|
|
return ERROR_INVALID_INDEX;
|
|
|
|
// Otherwise, delete it
|
|
pNicMap->usVirtMap[pNicMap->ppNics[i]->usVirtualId] = NIC_MAP_INVALID_NICID;
|
|
RtlFreeHeap(RtlProcessHeap(), 0, pNicMap->ppNics[i]->pNicInfo);
|
|
RtlFreeHeap(RtlProcessHeap(), 0, pNicMap->ppNics[i]);
|
|
pNicMap->ppNics[i] = NULL;
|
|
|
|
// Update the nic count and maximum nic id
|
|
if (i >= pNicMap->dwMaxNicId)
|
|
pNicMap->dwMaxNicId--;
|
|
pNicMap->dwNicCount--;
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
// Renumbers the nics in the table. dwOpCode is one
|
|
// of the NIC_OPCODE_XXX_XXX values
|
|
DWORD nmRenumber (NICMAP * pNicMap, USHORT usThreshold, DWORD dwOpCode) {
|
|
DWORD i;
|
|
|
|
// Increment the nic id's if needed
|
|
if (dwOpCode == NIC_OPCODE_INCREMENT_NICIDS) {
|
|
for (i = pNicMap->dwMaxNicId; i >= usThreshold; i--) {
|
|
pNicMap->ppNics[i+1] = pNicMap->ppNics[i];
|
|
if (pNicMap->ppNics[i])
|
|
pNicMap->usVirtMap[pNicMap->ppNics[i]->usVirtualId] = (USHORT)(i+1);
|
|
}
|
|
pNicMap->ppNics[usThreshold] = NULL;
|
|
}
|
|
|
|
// Else decrement them
|
|
else {
|
|
// If there is a nic there, delete it. This should never happen!
|
|
if (pNicMap->ppNics[usThreshold])
|
|
nmDelNic(pNicMap, pNicMap->ppNics[usThreshold]->pNicInfo);
|
|
|
|
// Renumber
|
|
for (i = usThreshold; i < pNicMap->dwMaxNicId; i++) {
|
|
if (pNicMap->ppNics[i+1])
|
|
pNicMap->usVirtMap[pNicMap->ppNics[i+1]->usVirtualId] = (USHORT)i;
|
|
pNicMap->ppNics[i] = pNicMap->ppNics[i+1];
|
|
}
|
|
if (pNicMap->ppNics[i])
|
|
pNicMap->ppNics[i] = NULL;
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
// Returns whether the nic map is empty
|
|
BOOL nmIsEmpty (NICMAP * pNicMap) {
|
|
return pNicMap->dwNicCount == 0;
|
|
}
|
|
|
|
|
|
// ========================================
|
|
// Implementation of the api used by adptif
|
|
// ========================================
|
|
|
|
DWORD NicMapInitialize() {
|
|
return nmInitialize(&GlobalNicIdMap);
|
|
}
|
|
|
|
DWORD NicMapCleanup() {
|
|
return nmCleanup(&GlobalNicIdMap);
|
|
}
|
|
|
|
USHORT NicMapGetVirtualNicId(USHORT usPhysId) {
|
|
return nmGetVirtualId(&GlobalNicIdMap, usPhysId);
|
|
}
|
|
|
|
USHORT NicMapGetPhysicalNicId(USHORT usVirtId) {
|
|
return nmGetPhysicalId(&GlobalNicIdMap, usVirtId);
|
|
}
|
|
|
|
DWORD NicMapGetMaxNicId() {
|
|
return nmGetMaxNicId(&GlobalNicIdMap);
|
|
}
|
|
|
|
DWORD NicMapGetNicCount() {
|
|
return nmGetNicCount(&GlobalNicIdMap);
|
|
}
|
|
|
|
DWORD NicMapAdd (IPX_NIC_INFO * pNic) {
|
|
return nmAddNic(&GlobalNicIdMap, pNic);
|
|
}
|
|
|
|
DWORD NicMapDel (IPX_NIC_INFO * pNic) {
|
|
return nmDelNic(&GlobalNicIdMap, pNic);
|
|
}
|
|
|
|
DWORD NicMapReconfigure (IPX_NIC_INFO * pNic) {
|
|
return nmReconfigure(&GlobalNicIdMap, pNic);
|
|
}
|
|
|
|
DWORD NicMapRenumber(DWORD dwOpCode, USHORT usThreshold) {
|
|
return nmRenumber (&GlobalNicIdMap, usThreshold, dwOpCode);
|
|
}
|
|
|
|
IPX_NIC_INFO * NicMapGetNicInfo (USHORT usNicId) {
|
|
return nmGetNicInfo (&GlobalNicIdMap, usNicId);
|
|
}
|
|
|
|
BOOL NicMapIsEmpty () {
|
|
return nmIsEmpty (&GlobalNicIdMap);
|
|
}
|
|
|
|
|