windows-nt/Source/XPSP1/NT/net/snmp/newagent/exe/subagnts.c
2020-09-26 16:20:57 +08:00

905 lines
19 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1992-1997 Microsoft Corporation
Module Name:
subagnts.c
Abstract:
Contains definitions for manipulating subagent structures.
Environment:
User Mode - Win32
Revision History:
10-Feb-1997 DonRyan
Rewrote to implement SNMPv2 support.
--*/
///////////////////////////////////////////////////////////////////////////////
// //
// Include files //
// //
///////////////////////////////////////////////////////////////////////////////
#include "globals.h"
#include "subagnts.h"
#include "regions.h"
#include "snmpmgmt.h"
///////////////////////////////////////////////////////////////////////////////
// //
// Private procedures //
// //
///////////////////////////////////////////////////////////////////////////////
BOOL
FindSubagent(
PSUBAGENT_LIST_ENTRY * ppSLE,
LPSTR pPathname
)
/*++
Routine Description:
Locates subagent in list.
Arguments:
ppSLE - pointer to receive pointer to entry.
pPathname - pointer to pathname to find.
Return Values:
Returns true if successful.
--*/
{
PLIST_ENTRY pLE;
PSUBAGENT_LIST_ENTRY pSLE;
// initialize
*ppSLE = NULL;
// obtain pointer to head
pLE = g_Subagents.Flink;
// process all entries in list
while (pLE != &g_Subagents) {
// retrieve pointer to trap destination structure
pSLE = CONTAINING_RECORD(pLE, SUBAGENT_LIST_ENTRY, Link);
// compare pathname string with entry
if (!strcmp(pSLE->pPathname, pPathname)) {
// transfer
*ppSLE = pSLE;
// success
return TRUE;
}
// next entry
pLE = pLE->Flink;
}
// failure
return FALSE;
}
BOOL
AddSubagentRegion(
PSUBAGENT_LIST_ENTRY pSLE,
AsnObjectIdentifier * pPrefixOid
)
/*++
Routine Description:
Adds subagent supported region to structure.
Arguments:
pSLE - pointer to subagent structure.
pPrefixOid - pointer to supported region.
Return Values:
Returns true if successful.
--*/
{
BOOL fOk = FALSE;
PMIB_REGION_LIST_ENTRY pRLE = NULL;
// allocate region
if (AllocRLE(&pRLE)) {
// save pointer
pRLE->pSLE = pSLE;
// copy prefix to structure
SnmpUtilOidCpy(&pRLE->PrefixOid, pPrefixOid);
// copy prefix as temporary limit
SnmpUtilOidCpy(&pRLE->LimitOid, pPrefixOid);
// modify limit oid to be one past the prefix
++pRLE->LimitOid.ids[pRLE->LimitOid.idLength - 1];
SNMPDBG((
SNMP_LOG_TRACE,
"SNMP: SVC: %s supports %s.\n",
pSLE->pPathname,
SnmpUtilOidToA(&pRLE->PrefixOid)
));
// attach to mib region to subagent structure
InsertTailList(&pSLE->SupportedRegions, &pRLE->Link);
// success
fOk = TRUE;
}
return fOk;
}
BOOL
OfferInternalMgmtVariables(
PSUBAGENT_LIST_ENTRY pSLE
)
/*++
Routine Description:
if the subagent is willing to monitor the SNMP service
this function is offering it a pointer to the internal
management variables
Arguments:
pSLE - pointer to subagent structure.
Return Values:
Returns true anyway.
--*/
{
if (pSLE->pfnSnmpExtensionMonitor != NULL)
{
__try {
// attempt to initialize agent
(*pSLE->pfnSnmpExtensionMonitor)(&snmpMgmtBase);
} __except (EXCEPTION_EXECUTE_HANDLER) {
SNMPDBG((
SNMP_LOG_ERROR,
"SNMP: SVC: exception 0x%08lx offering internals to %s.\n",
GetExceptionCode(),
pSLE->pPathname
));
// failure
return FALSE;
}
}
return TRUE;
}
BOOL
LoadSubagentRegions(
PSUBAGENT_LIST_ENTRY pSLE
)
/*++
Routine Description:
Loads subagent supported regions.
Arguments:
pSLE - pointer to subagent structure.
Return Values:
Returns true if successful.
--*/
{
BOOL fOk = FALSE;
HANDLE hSubagentTrapEvent = NULL;
AsnObjectIdentifier PrefixOid = { 0, NULL };
__try {
// attempt to initialize agent
if ((*pSLE->pfnSnmpExtensionInit)(
g_dwUpTimeReference,
&hSubagentTrapEvent,
&PrefixOid
)) {
// store subagent trap event handle
pSLE->hSubagentTrapEvent = hSubagentTrapEvent;
// add subagent region to list entry
fOk = AddSubagentRegion(pSLE, &PrefixOid);
// check to see if subagent supports additional regions
if (fOk && (pSLE->pfnSnmpExtensionInitEx != NULL)) {
BOOL fMoreRegions = TRUE;
// get other regions
while (fOk && fMoreRegions) {
// retrieve next supported region
fMoreRegions = (*pSLE->pfnSnmpExtensionInitEx)(
&PrefixOid
);
// validate
if (fMoreRegions) {
// add subagent region to list entry
fOk = AddSubagentRegion(pSLE, &PrefixOid);
}
}
}
}
} __except (EXCEPTION_EXECUTE_HANDLER) {
SNMPDBG((
SNMP_LOG_ERROR,
"SNMP: SVC: exception 0x%08lx loading %s.\n",
GetExceptionCode(),
pSLE->pPathname
));
// failure
fOk = FALSE;
}
return fOk;
}
BOOL
LoadSubagent(
PSUBAGENT_LIST_ENTRY pSLE
)
/*++
Routine Description:
Loads subagent dll and initializes.
Arguments:
pSLE - pointer to subagent structure.
Return Values:
Returns true if successful.
--*/
{
BOOL fOk = FALSE;
// attempt to load subagent library - we use the altered search path flag so that
// the subagent can load DLLs that live in its directory
pSLE->hSubagentDll = LoadLibraryExA(pSLE->pPathname, 0, LOAD_WITH_ALTERED_SEARCH_PATH);
// validate handle
if (pSLE->hSubagentDll != NULL) {
// load primary initialization routine
pSLE->pfnSnmpExtensionInit = (PFNSNMPEXTENSIONINIT)
GetProcAddress(
pSLE->hSubagentDll,
SNMP_EXTENSION_INIT
);
// load secondary initialization routine
pSLE->pfnSnmpExtensionInitEx = (PFNSNMPEXTENSIONINITEX)
GetProcAddress(
pSLE->hSubagentDll,
SNMP_EXTENSION_INIT_EX
);
// load secondary initialization routine
pSLE->pfnSnmpExtensionClose = (PFNSNMPEXTENSIONCLOSE)
GetProcAddress(
pSLE->hSubagentDll,
SNMP_EXTENSION_CLOSE
);
// load the extension monitor routine
pSLE->pfnSnmpExtensionMonitor = (PFNSNMPEXTENSIONMONITOR)
GetProcAddress(
pSLE->hSubagentDll,
SNMP_EXTENSION_MONITOR
);
// load snmpv1-based subagent request routine
pSLE->pfnSnmpExtensionQuery = (PFNSNMPEXTENSIONQUERY)
GetProcAddress(
pSLE->hSubagentDll,
SNMP_EXTENSION_QUERY
);
// load snmpv2-based subagent request routine
pSLE->pfnSnmpExtensionQueryEx = (PFNSNMPEXTENSIONQUERYEX)
GetProcAddress(
pSLE->hSubagentDll,
SNMP_EXTENSION_QUERY_EX
);
// load snmpv1-based subagent trap routine
pSLE->pfnSnmpExtensionTrap = (PFNSNMPEXTENSIONTRAP)
GetProcAddress(
pSLE->hSubagentDll,
SNMP_EXTENSION_TRAP
);
// validate subagent agent entry points
if ((pSLE->pfnSnmpExtensionInit != NULL) &&
((pSLE->pfnSnmpExtensionQuery != NULL) ||
(pSLE->pfnSnmpExtensionQueryEx != NULL))) {
// load supported regions
if (fOk = LoadSubagentRegions(pSLE)) // !!intentional assignement!!
{
// offering internal management variables;
fOk = OfferInternalMgmtVariables(pSLE);
}
}
}
else
{
DWORD errCode = GetLastError();
LPTSTR pPathname;
#ifdef UNICODE
SnmpUtilUTF8ToUnicode(&pPathname, pSLE->pPathname, TRUE);
#else
pPathname = pSLE->pPathname;
#endif
SNMPDBG((
SNMP_LOG_ERROR,
"SNMP: SVC: error %d loading subagent.\n",
errCode
));
ReportSnmpEvent(
SNMP_EVENT_INVALID_EXTENSION_AGENT_DLL,
1,
&pPathname,
errCode);
#ifdef UNICODE
SnmpUtilMemFree(pPathname);
#endif
}
return fOk;
}
BOOL
AddSubagentByDll(
LPSTR pPathname,
UCHAR uchInitFlags
)
/*++
Routine Description:
Adds subagent to list.
Arguments:
pPathname - pointer to subagent's dll path.
Return Values:
Returns true if successful.
--*/
{
BOOL fOk = FALSE;
PSUBAGENT_LIST_ENTRY pSLE = NULL;
// attempt to locate in list
if (FindSubagent(&pSLE, pPathname)) {
SNMPDBG((
SNMP_LOG_WARNING,
"SNMP: SVC: duplicate entry for %s.\n",
pPathname
));
// success
fOk = TRUE;
} else {
// allocate subagent structure
if (AllocSLE(&pSLE, pPathname, uchInitFlags)) {
SNMPDBG((
SNMP_LOG_TRACE,
"SNMP: SVC: processing subagent %s.\n",
pPathname
));
// initialize subagent
if (LoadSubagent(pSLE)) {
// insert into valid communities list
InsertTailList(&g_Subagents, &pSLE->Link);
// success
fOk = TRUE;
}
// cleanup
if (!fOk) {
// release
FreeSLE(pSLE);
}
}
}
return fOk;
}
BOOL
AddSubagentByKey(
LPTSTR pKey
)
/*++
Routine Description:
Adds subagent to list.
Arguments:
pKey - pointer to subagent's registry key path.
Return Values:
Returns true if successful.
--*/
{
HKEY hKey;
LONG lStatus;
DWORD dwIndex;
DWORD dwNameSize;
DWORD dwValueSize;
DWORD dwValueType;
CHAR szName[MAX_PATH];
CHAR szValue[MAX_PATH];
BOOL fOk = FALSE;
PSUBAGENT_LIST_ENTRY pSLE = NULL;
// open registry subkey
lStatus = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
pKey,
0,
KEY_READ,
&hKey
);
// validate return code
if (lStatus == ERROR_SUCCESS) {
// initialize
dwIndex = 0;
// initialize buffer sizes
dwNameSize = sizeof(szName);
dwValueSize = sizeof(szValue);
// loop until error or end of list
while (lStatus == ERROR_SUCCESS) {
// read next value
lStatus = RegEnumValueA(
hKey,
dwIndex,
szName,
&dwNameSize,
NULL,
&dwValueType,
szValue,
&dwValueSize
);
// validate return code
if (lStatus == ERROR_SUCCESS) {
// check to see if value is pathname
if (!_stricmp(szName, REG_VALUE_SUBAGENT_PATH)) {
DWORD dwRequired;
CHAR szExpanded[MAX_PATH];
// expand environment strings in path
dwRequired = ExpandEnvironmentStringsA(
szValue,
szExpanded,
sizeof(szExpanded)
);
// load subagent library - no flags set
fOk = AddSubagentByDll(szExpanded, 0);
break; // bail...
}
// initialize buffer sizes
dwNameSize = sizeof(szName);
dwValueSize = sizeof(szValue);
// next
dwIndex++;
} else if (lStatus == ERROR_NO_MORE_ITEMS) {
// failure
fOk = FALSE;
}
}
// release handle
RegCloseKey(hKey);
}
else
{
// the registry key for this subagent could not be located.
ReportSnmpEvent(
SNMP_EVENT_INVALID_EXTENSION_AGENT_KEY,
1,
&pKey,
lStatus);
}
return fOk;
}
///////////////////////////////////////////////////////////////////////////////
// //
// Public procedures //
// //
///////////////////////////////////////////////////////////////////////////////
BOOL
AllocSLE(
PSUBAGENT_LIST_ENTRY * ppSLE,
LPSTR pPathname,
UCHAR uchInitFlags
)
/*++
Routine Description:
Allocates trap destination structure and initializes.
Arguments:
ppSLE - pointer to receive pointer to entry.
pPathname - pointer to subgent's dll path.
Return Values:
Returns true if successful.
--*/
{
BOOL fOk = FALSE;
PSUBAGENT_LIST_ENTRY pSLE = NULL;
// attempt to allocate structure
pSLE = AgentMemAlloc(sizeof(SUBAGENT_LIST_ENTRY));
// validate
if (pSLE != NULL) {
// allocate memory for trap destination string
pSLE->pPathname = AgentMemAlloc(strlen(pPathname)+1);
// validate
if (pSLE->pPathname != NULL) {
// transfer trap destination string
strcpy(pSLE->pPathname, pPathname);
// set the initial flags value
pSLE->uchFlags = uchInitFlags;
// initialize list of supported regions
InitializeListHead(&pSLE->SupportedRegions);
// success
fOk = TRUE;
}
// cleanup
if (!fOk) {
// release
FreeSLE(pSLE);
// re-init
pSLE = NULL;
}
}
// transfer
*ppSLE = pSLE;
return fOk;
}
BOOL
FreeSLE(
PSUBAGENT_LIST_ENTRY pSLE
)
/*++
Routine Description:
Releases subagent structure.
Arguments:
pSLE - pointer to list entry to be freed.
Return Values:
Returns true if successful.
--*/
{
BOOL fOk = TRUE;
// validate pointer
if (pSLE != NULL) {
SNMPDBG((
SNMP_LOG_VERBOSE,
"SNMP: SVC: unloading %s.\n",
pSLE->pPathname
));
// release manager structures
UnloadRegions(&pSLE->SupportedRegions);
// validate subagent dll handle
if (pSLE->hSubagentDll != NULL) {
__try {
if (pSLE->pfnSnmpExtensionClose != NULL)
(*pSLE->pfnSnmpExtensionClose)();
// unload subagent
FreeLibrary(pSLE->hSubagentDll);
} __except (EXCEPTION_EXECUTE_HANDLER) {
SNMPDBG((
SNMP_LOG_ERROR,
"SNMP: SVC: exception 0x%08lx unloading %s.\n",
GetExceptionCode(),
pSLE->pPathname
));
}
}
// release string
AgentMemFree(pSLE->pPathname);
// release structure
AgentMemFree(pSLE);
}
return TRUE;
}
BOOL
LoadSubagents(
)
/*++
Routine Description:
Constructs list of subagents.
Arguments:
None.
Return Values:
Returns true if successful.
--*/
{
HKEY hKey;
LONG lStatus;
DWORD dwIndex;
DWORD dwNameSize;
DWORD dwValueSize;
DWORD dwValueType;
TCHAR szName[MAX_PATH];
TCHAR szValue[MAX_PATH];
LPTSTR pszKey = REG_KEY_EXTENSION_AGENTS;
BOOL fOk = FALSE;
SNMPDBG((
SNMP_LOG_TRACE,
"SNMP: SVC: loading subagents.\n"
));
// open registry subkey
lStatus = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
pszKey,
0,
KEY_READ,
&hKey
);
// validate return code
if (lStatus == ERROR_SUCCESS) {
// initialize
dwIndex = 0;
// initialize buffer sizes
dwNameSize = sizeof(szName) / sizeof(szName[0]); // size in number of TCHARs
dwValueSize = sizeof(szValue); // size in number of bytes
// loop until error or end of list
while (lStatus == ERROR_SUCCESS) {
// read next value
lStatus = RegEnumValue(
hKey,
dwIndex,
szName,
&dwNameSize,
NULL,
&dwValueType,
(LPBYTE)szValue,
&dwValueSize
);
// validate return code
if (lStatus == ERROR_SUCCESS) {
// add subagent to list
AddSubagentByKey(szValue);
// re-initialize buffer sizes
dwNameSize = sizeof(szName) / sizeof(szName[0]); // size in number of TCHARs
dwValueSize = sizeof(szValue); // size in number of bytes
// next
dwIndex++;
} else if (lStatus == ERROR_NO_MORE_ITEMS) {
// success
fOk = TRUE;
}
}
}
if (!fOk) {
SNMPDBG((
SNMP_LOG_ERROR,
"SNMP: SVC: error %d processing Subagents subkey.\n",
lStatus
));
// report event
ReportSnmpEvent(
SNMP_EVENT_INVALID_REGISTRY_KEY,
1,
&pszKey,
lStatus
);
}
return fOk;
}
BOOL
UnloadSubagents(
)
/*++
Routine Description:
Destroys list of subagents.
Arguments:
None.
Return Values:
Returns true if successful.
--*/
{
PLIST_ENTRY pLE;
PSUBAGENT_LIST_ENTRY pSLE;
// process entries until list is empty
while (!IsListEmpty(&g_Subagents)) {
// extract next entry from head of list
pLE = RemoveHeadList(&g_Subagents);
// retrieve pointer to community structure
pSLE = CONTAINING_RECORD(pLE, SUBAGENT_LIST_ENTRY, Link);
// release
FreeSLE(pSLE);
}
return TRUE;
}