windows-nt/Source/XPSP1/NT/net/snmp/newagent/exe/regions.c

893 lines
20 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 1992-1997 Microsoft Corporation
Module Name:
regions.c
Abstract:
Contains routines for manipulating MIB region structures.
Environment:
User Mode - Win32
Revision History:
10-Feb-1997 DonRyan
Rewrote to implement SNMPv2 support.
--*/
///////////////////////////////////////////////////////////////////////////////
// //
// Header files //
// //
///////////////////////////////////////////////////////////////////////////////
#include "globals.h"
#include "subagnts.h"
#include "regions.h"
///////////////////////////////////////////////////////////////////////////////
// //
// Private procedures //
// //
///////////////////////////////////////////////////////////////////////////////
BOOL
UpdateSupportedRegion(
PMIB_REGION_LIST_ENTRY pExistingRLE,
PMIB_REGION_LIST_ENTRY pRLE
)
/*++
Routine Description:
Updates MIB region properties based on supporting subagent.
Arguments:
pExisingRLE - pointer to existing MIB region to be updated.
pRLE - pointer to subagent MIB region to be analyzed and saved.
Return Values:
Returns true if successful.
--*/
{
INT nDiff;
PMIB_REGION_LIST_ENTRY pSubagentRLE;
// see if source is subagent
if (pRLE->pSubagentRLE == NULL) {
// save pointer
pSubagentRLE = pRLE;
} else {
// save pointer
pSubagentRLE = pRLE->pSubagentRLE;
}
// see if target uninitialized
if (pExistingRLE->pSubagentRLE == NULL) {
// save pointer to subagent region
pExistingRLE->pSubagentRLE = pSubagentRLE;
// save pointer to supporting subagent
pExistingRLE->pSLE = pSubagentRLE->pSLE;
} else {
UINT nSubIds1;
UINT nSubIds2;
// determine length of existing subagent's original prefix
nSubIds1 = pExistingRLE->pSubagentRLE->PrefixOid.idLength;
// determine length of new subagent's prefix
nSubIds2 = pSubagentRLE->PrefixOid.idLength;
// update if more specific
if (nSubIds1 <= nSubIds2) {
// save pointer to subagent region
pExistingRLE->pSubagentRLE = pSubagentRLE;
// save pointer to supporting subagent
pExistingRLE->pSLE = pSubagentRLE->pSLE;
}
}
return TRUE;
}
BOOL
SplitSupportedRegion(
PMIB_REGION_LIST_ENTRY pRLE1,
PMIB_REGION_LIST_ENTRY pRLE2,
PMIB_REGION_LIST_ENTRY * ppLastSplitRLE
)
/*++
Routine Description:
Splits existing MIB region in order to insert new region.
Arguments:
pRLE1 - pointer to first MIB region to be split.
pRLE2 - pointer to second MIB region to be split (not released).
ppLastSplitRLE - pointer to receiver pointer to last split MIB region.
Return Values:
Returns true if successful.
--*/
{
INT nLimitDiff;
INT nPrefixDiff;
PMIB_REGION_LIST_ENTRY pRLE3 = NULL;
PMIB_REGION_LIST_ENTRY pRLE4 = NULL;
PMIB_REGION_LIST_ENTRY pRLE5 = NULL;
BOOL fOk = TRUE;
// allocate regions
if (!AllocRLE(&pRLE3) ||
!AllocRLE(&pRLE4) ||
!AllocRLE(&pRLE5)) {
// release
FreeRLE(pRLE3);
FreeRLE(pRLE4);
FreeRLE(pRLE5);
// failure
return FALSE;
}
// initialize pointer
*ppLastSplitRLE = pRLE5;
// calculate difference betweeen mib region limits
nLimitDiff = SnmpUtilOidCmp(&pRLE1->LimitOid, &pRLE2->LimitOid);
// calculate difference betweeen mib region prefixes
nPrefixDiff = SnmpUtilOidCmp(&pRLE1->PrefixOid, &pRLE2->PrefixOid);
// check for same prefix
if (nPrefixDiff != 0) {
// first prefix less
if (nPrefixDiff < 0) {
// r3.prefix equals min(rl.prefix,r2.prefix)
SnmpUtilOidCpy(&pRLE3->PrefixOid, &pRLE1->PrefixOid);
// r3.limit equals max(rl.prefix,r2.prefix)
SnmpUtilOidCpy(&pRLE3->LimitOid, &pRLE2->PrefixOid);
// r3 is supported by r1 subagent
UpdateSupportedRegion(pRLE3, pRLE1);
} else {
// r3.prefix equals min(rl.prefix,r2.prefix)
SnmpUtilOidCpy(&pRLE3->PrefixOid, &pRLE2->PrefixOid);
// r3.limit equals max(rl.prefix,r2.prefix)
SnmpUtilOidCpy(&pRLE3->LimitOid, &pRLE1->PrefixOid);
// r3 is supported by r2 subagent
UpdateSupportedRegion(pRLE3, pRLE2);
}
// r4.prefix equals r3.limit
SnmpUtilOidCpy(&pRLE4->PrefixOid, &pRLE3->LimitOid);
// r4 is supported by both subagents
UpdateSupportedRegion(pRLE4, pRLE1);
UpdateSupportedRegion(pRLE4, pRLE2);
// first limit less
if (nLimitDiff < 0) {
// r4.limit equals min(rl.limit,r2.limit)
SnmpUtilOidCpy(&pRLE4->LimitOid, &pRLE1->LimitOid);
// r5.prefix equals r4.limit
SnmpUtilOidCpy(&pRLE5->PrefixOid, &pRLE4->LimitOid);
// r5.limit equals max(rl.limit,r2.limit)
SnmpUtilOidCpy(&pRLE5->LimitOid, &pRLE2->LimitOid);
// r5 is supported by r2 subagent
UpdateSupportedRegion(pRLE5, pRLE2);
// insert third mib region into list first
InsertHeadList(&pRLE1->Link, &pRLE5->Link);
} else if (nLimitDiff > 0) {
// r4.limit equals min(rl.limit,r2.limit)
SnmpUtilOidCpy(&pRLE4->LimitOid, &pRLE2->LimitOid);
// r5.prefix equals r4.limit
SnmpUtilOidCpy(&pRLE5->PrefixOid, &pRLE4->LimitOid);
// r5.limit equals max(rl.limit,r2.limit)
SnmpUtilOidCpy(&pRLE5->LimitOid, &pRLE1->LimitOid);
// r5 is supported by r1 subagent
UpdateSupportedRegion(pRLE5, pRLE1);
// insert third mib region into list first
InsertHeadList(&pRLE1->Link, &pRLE5->Link);
} else {
// r4.limit equals min(rl.limit,r2.limit)
SnmpUtilOidCpy(&pRLE4->LimitOid, &pRLE2->LimitOid);
// return r4 as last
*ppLastSplitRLE = pRLE4;
// release
FreeRLE(pRLE5);
}
// insert remaining mib regions into list
InsertHeadList(&pRLE1->Link, &pRLE4->Link);
InsertHeadList(&pRLE1->Link, &pRLE3->Link);
// remove existing
RemoveEntryList(&pRLE1->Link);
// release
FreeRLE(pRLE1);
} else if (nLimitDiff != 0) {
// r3.prefix equals same prefix for r1 and r2
SnmpUtilOidCpy(&pRLE3->PrefixOid, &pRLE1->PrefixOid);
// r3 is supported by both subagents
UpdateSupportedRegion(pRLE3, pRLE1);
UpdateSupportedRegion(pRLE3, pRLE2);
// first limit less
if (nLimitDiff < 0) {
// r3.limit equals min(rl.limit,r2.limit)
SnmpUtilOidCpy(&pRLE3->LimitOid, &pRLE1->LimitOid);
// r4.prefix equals r3.limit
SnmpUtilOidCpy(&pRLE4->PrefixOid, &pRLE3->LimitOid);
// r4.limit equals max(rl.limit,r2.limit)
SnmpUtilOidCpy(&pRLE4->LimitOid, &pRLE2->LimitOid);
// r4 is supported by r2 subagent
UpdateSupportedRegion(pRLE4, pRLE2);
} else {
// r3.limit equals min(rl.limit,r2.limit)
SnmpUtilOidCpy(&pRLE3->LimitOid, &pRLE2->LimitOid);
// r4.prefix equals r3.limit
SnmpUtilOidCpy(&pRLE4->PrefixOid, &pRLE3->LimitOid);
// r4.limit equals max(rl.limit,r2.limit)
SnmpUtilOidCpy(&pRLE4->LimitOid, &pRLE1->LimitOid);
// r4 is supported by r1 subagent
UpdateSupportedRegion(pRLE4, pRLE1);
}
// return r4 as last
*ppLastSplitRLE = pRLE4;
// insert mib regions into list
InsertHeadList(&pRLE1->Link, &pRLE4->Link);
InsertHeadList(&pRLE1->Link, &pRLE3->Link);
// remove existing
RemoveEntryList(&pRLE1->Link);
// release
FreeRLE(pRLE1);
FreeRLE(pRLE5);
} else {
// region supported existing subagent
UpdateSupportedRegion(pRLE1, pRLE2);
// return r1 as last
*ppLastSplitRLE = pRLE1;
// release
FreeRLE(pRLE3);
FreeRLE(pRLE4);
FreeRLE(pRLE5);
}
// success
return TRUE;
}
BOOL
InsertSupportedRegion(
PMIB_REGION_LIST_ENTRY pExistingRLE,
PMIB_REGION_LIST_ENTRY pRLE
)
/*++
Routine Description:
Splits existing MIB region in order to insert new region.
Arguments:
pExisingRLE - pointer to existing MIB region to be split.
pRLE - pointer to MIB region to be inserted.
Return Values:
Returns true if successful.
--*/
{
BOOL fOk;
PLIST_ENTRY pLE;
PMIB_REGION_LIST_ENTRY pLastSplitRLE = NULL;
INT nDiff;
// attempt to split mib regions into pieces parts
fOk = SplitSupportedRegion(pExistingRLE, pRLE, &pLastSplitRLE);
// process remaining entries
while (pLastSplitRLE != NULL) {
// re-use stack pointer
pExistingRLE = pLastSplitRLE;
// re-initialize
pLastSplitRLE = NULL;
// obtain pointer to next entry
pLE = pExistingRLE->Link.Flink;
// make sure entries remaining
if (pLE != &g_SupportedRegions) {
// retrieve pointer to mib region that follows last split one
pRLE = CONTAINING_RECORD(pLE, MIB_REGION_LIST_ENTRY, Link);
// compare mib regions
nDiff = SnmpUtilOidCmp(
&pExistingRLE->LimitOid,
&pRLE->PrefixOid
);
// overlapped?
if (nDiff > 0) {
// remove from list
RemoveEntryList(&pRLE->Link);
// split the two new overlapped mib regions
SplitSupportedRegion(pExistingRLE, pRLE, &pLastSplitRLE);
// release
FreeRLE(pRLE);
}
}
}
return fOk;
}
/*---debug purpose only----
void PrintSupportedRegion()
{
PLIST_ENTRY pLE;
PMIB_REGION_LIST_ENTRY pRLE;
// obtain pointer to list head
pLE = g_SupportedRegions.Flink;
// process all entries in list
while (pLE != &g_SupportedRegions) {
// retrieve pointer to mib region structure
pRLE = CONTAINING_RECORD(pLE, MIB_REGION_LIST_ENTRY, Link);
SNMPDBG((SNMP_LOG_VERBOSE,"\t[%s\n", SnmpUtilOidToA(&(pRLE->PrefixOid))));
SNMPDBG((SNMP_LOG_VERBOSE,"\t\t%s]\n", SnmpUtilOidToA(&(pRLE->LimitOid))));
// next entry
pLE = pLE->Flink;
}
SNMPDBG((SNMP_LOG_VERBOSE,"----\n"));
}
*/
BOOL
AddSupportedRegion(
PMIB_REGION_LIST_ENTRY pRLE
)
/*++
Routine Description:
Add subagent's MIB region into master agent's list.
Arguments:
pRLE - pointer to MIB region to add to supported list.
Return Values:
Returns true if successful.
--*/
{
PLIST_ENTRY pLE;
PMIB_REGION_LIST_ENTRY pRLE2;
PMIB_REGION_LIST_ENTRY pExistingRLE;
BOOL fFoundOk = FALSE;
BOOL fOk = FALSE;
INT nDiff;
// PrintSupportedRegion();
// attempt to locate prefix in existing mib regions
if (FindFirstOverlappingRegion(&pExistingRLE, pRLE)) {
// split existing region into bits
fOk = InsertSupportedRegion(pExistingRLE, pRLE);
} else {
// obtain pointer to list head
pLE = g_SupportedRegions.Flink;
// process all entries in list
while (pLE != &g_SupportedRegions) {
// retrieve pointer to mib region
pExistingRLE = CONTAINING_RECORD(pLE, MIB_REGION_LIST_ENTRY, Link);
// compare region prefix
nDiff = SnmpUtilOidCmp(&pRLE->PrefixOid, &pExistingRLE->PrefixOid);
// found match?
if (nDiff < 0) {
// success
fFoundOk = TRUE;
break; // bail...
}
// next entry
pLE = pLE->Flink;
}
// validate pointer
if (AllocRLE(&pRLE2)) {
// transfer prefix oid from subagent region
SnmpUtilOidCpy(&pRLE2->PrefixOid, &pRLE->PrefixOid);
// transfer limit oid from subagent region
SnmpUtilOidCpy(&pRLE2->LimitOid, &pRLE->LimitOid);
// save region pointer
pRLE2->pSubagentRLE = pRLE;
// save subagent pointer
pRLE2->pSLE = pRLE->pSLE;
// validate
if (fFoundOk) {
// add new mib range into supported list
InsertTailList(&pExistingRLE->Link, &pRLE2->Link);
} else {
// add new mib range into global supported list
InsertTailList(&g_SupportedRegions, &pRLE2->Link);
}
// success
fOk = TRUE;
}
}
return fOk;
}
///////////////////////////////////////////////////////////////////////////////
// //
// Public procedures //
// //
///////////////////////////////////////////////////////////////////////////////
BOOL
AllocRLE(
PMIB_REGION_LIST_ENTRY * ppRLE
)
/*++
Routine Description:
Allocates MIB region structure and initializes.
Arguments:
ppRLE - pointer to receive pointer to list entry.
Return Values:
Returns true if successful.
--*/
{
BOOL fOk = FALSE;
PMIB_REGION_LIST_ENTRY pRLE;
// attempt to allocate structure
pRLE = AgentMemAlloc(sizeof(MIB_REGION_LIST_ENTRY));
// validate pointer
if (pRLE != NULL) {
// initialize links
InitializeListHead(&pRLE->Link);
// success
fOk = TRUE;
} else {
SNMPDBG((
SNMP_LOG_ERROR,
"SNMP: SVC: could not allocate region entry.\n"
));
}
// transfer
*ppRLE = pRLE;
return fOk;
}
BOOL
FreeRLE(
PMIB_REGION_LIST_ENTRY pRLE
)
/*++
Routine Description:
Releases MIB region structure.
Arguments:
ppRLE - pointer to MIB region to be freed.
Return Values:
Returns true if successful.
--*/
{
// validate pointer
if (pRLE != NULL) {
// release memory for prefix oid
SnmpUtilOidFree(&pRLE->PrefixOid);
// release memory for limit oid
SnmpUtilOidFree(&pRLE->LimitOid);
// release memory
AgentMemFree(pRLE);
}
return TRUE;
}
BOOL
UnloadRegions(
PLIST_ENTRY pListHead
)
/*++
Routine Description:
Destroys list of MIB regions.
Arguments:
pListHead - pointer to list of regions.
Return Values:
Returns true if successful.
--*/
{
PLIST_ENTRY pLE;
PMIB_REGION_LIST_ENTRY pRLE;
// process entries until empty
while (!IsListEmpty(pListHead)) {
// extract next entry from head
pLE = RemoveHeadList(pListHead);
// retrieve pointer to mib region structure
pRLE = CONTAINING_RECORD(pLE, MIB_REGION_LIST_ENTRY, Link);
// release
FreeRLE(pRLE);
}
return TRUE;
}
BOOL
FindFirstOverlappingRegion(
PMIB_REGION_LIST_ENTRY * ppRLE,
PMIB_REGION_LIST_ENTRY pNewRLE
)
/*++
Routine Description:
Detects if any existent region overlapps with the new one to be added.
Arguments:
ppRLE - pointer to receive pointer to list entry.
pNewRLE - pointer to new region to be tested
Return Values:
Returns true if match found.
--*/
{
PLIST_ENTRY pLE;
PMIB_REGION_LIST_ENTRY pRLE;
// initialize
*ppRLE = NULL;
// obtain pointer to list head
pLE = g_SupportedRegions.Flink;
// process all entries in list
while (pLE != &g_SupportedRegions) {
// retrieve pointer to mib region structure
pRLE = CONTAINING_RECORD(pLE, MIB_REGION_LIST_ENTRY, Link);
if (SnmpUtilOidCmp(&pNewRLE->PrefixOid, &pRLE->LimitOid) < 0 &&
SnmpUtilOidCmp(&pNewRLE->LimitOid, &pRLE->PrefixOid) > 0)
{
*ppRLE = pRLE;
return TRUE;
}
// next entry
pLE = pLE->Flink;
}
// failure
return FALSE;
}
BOOL
FindSupportedRegion(
PMIB_REGION_LIST_ENTRY * ppRLE,
AsnObjectIdentifier * pPrefixOid,
BOOL fAnyOk
)
/*++
Routine Description:
Locates MIB region in list.
Arguments:
ppRLE - pointer to receive pointer to list entry.
pPrefixOid - pointer to OID to locate within MIB region.
fAnyOk - true if exact match not necessary.
Return Values:
Returns true if match found.
--*/
{
PLIST_ENTRY pLE;
PMIB_REGION_LIST_ENTRY pRLE;
INT nDiff;
// initialize
*ppRLE = NULL;
// obtain pointer to list head
pLE = g_SupportedRegions.Flink;
// process all entries in list
while (pLE != &g_SupportedRegions) {
// retrieve pointer to mib region structure
pRLE = CONTAINING_RECORD(pLE, MIB_REGION_LIST_ENTRY, Link);
// region prefix should be also the prefix for the given OID
nDiff = SnmpUtilOidNCmp(pPrefixOid, &pRLE->PrefixOid, pRLE->PrefixOid.idLength);
// found match?
if ((nDiff < 0 && fAnyOk) ||
(nDiff == 0 && SnmpUtilOidCmp(pPrefixOid, &pRLE->LimitOid) < 0))
{
*ppRLE = pRLE;
return TRUE;
}
// next entry
pLE = pLE->Flink;
}
// failure
return FALSE;
}
BOOL
LoadSupportedRegions(
)
/*++
Routine Description:
Creates global list of supported MIB regions from subagent MIB regions.
Arguments:
None.
Return Values:
Returns true if successful.
--*/
{
PLIST_ENTRY pLE1;
PLIST_ENTRY pLE2;
PSUBAGENT_LIST_ENTRY pSLE;
PMIB_REGION_LIST_ENTRY pRLE;
// get subagent list head
pLE1 = g_Subagents.Flink;
// process all entries in list
while (pLE1 != &g_Subagents) {
// retrieve pointer to subagent structure
pSLE = CONTAINING_RECORD(pLE1, SUBAGENT_LIST_ENTRY, Link);
SNMPDBG((
SNMP_LOG_VERBOSE,
"SNMP: SVC: Scan views supported by %s.\n",
pSLE->pPathname
));
// get supported regions list head
pLE2 = pSLE->SupportedRegions.Flink;
// process all entries in list
while (pLE2 != &pSLE->SupportedRegions) {
// retrieve pointer to mib region structure
pRLE = CONTAINING_RECORD(pLE2, MIB_REGION_LIST_ENTRY, Link);
SNMPDBG((
SNMP_LOG_VERBOSE,
"SNMP: SVC: view %s\n",
SnmpUtilOidToA(&pRLE->PrefixOid)
));
// attempt to add mib region
if (!AddSupportedRegion(pRLE)) {
// failure
return FALSE;
}
// next mib region
pLE2 = pLE2->Flink;
}
// next subagent
pLE1 = pLE1->Flink;
}
// success
return TRUE;
}
BOOL
UnloadSupportedRegions(
)
/*++
Routine Description:
Destroys list of MIB regions.
Arguments:
None.
Return Values:
Returns true if successful.
--*/
{
// unload global supported regions
return UnloadRegions(&g_SupportedRegions);
}