1552 lines
37 KiB
C
1552 lines
37 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1992-1997 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
query.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
Contains routines for querying subagents.
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
User Mode - Win32
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
10-Feb-1997 DonRyan
|
|||
|
Rewrote to implement SNMPv2 support.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
///////////////////////////////////////////////////////////////////////////////
|
|||
|
// //
|
|||
|
// Include files //
|
|||
|
// //
|
|||
|
///////////////////////////////////////////////////////////////////////////////
|
|||
|
|
|||
|
#include "globals.h"
|
|||
|
#include "varbinds.h"
|
|||
|
#include "network.h"
|
|||
|
#include "query.h"
|
|||
|
#include "snmpmgmt.h"
|
|||
|
|
|||
|
|
|||
|
///////////////////////////////////////////////////////////////////////////////
|
|||
|
// //
|
|||
|
// Private procedures //
|
|||
|
// //
|
|||
|
///////////////////////////////////////////////////////////////////////////////
|
|||
|
|
|||
|
BOOL
|
|||
|
FindQueryBySLE(
|
|||
|
PQUERY_LIST_ENTRY * ppQLE,
|
|||
|
PNETWORK_LIST_ENTRY pNLE,
|
|||
|
PSUBAGENT_LIST_ENTRY pSLE
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Allocates query list entry.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
ppQLE - pointer to receive query entry pointer.
|
|||
|
|
|||
|
pNLE - pointer to network list entry.
|
|||
|
|
|||
|
pSLE - pointer to subagent list entry.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Returns true if successful.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PLIST_ENTRY pLE;
|
|||
|
PQUERY_LIST_ENTRY pQLE = NULL;
|
|||
|
|
|||
|
// point to first query
|
|||
|
pLE = pNLE->Queries.Flink;
|
|||
|
|
|||
|
// process each query
|
|||
|
while (pLE != &pNLE->Queries) {
|
|||
|
|
|||
|
// retrieve pointer to query entry from link
|
|||
|
pQLE = CONTAINING_RECORD(pLE, QUERY_LIST_ENTRY, Link);
|
|||
|
|
|||
|
// compare subagents
|
|||
|
if (pQLE->pSLE == pSLE) {
|
|||
|
|
|||
|
// transfer
|
|||
|
*ppQLE = pQLE;
|
|||
|
|
|||
|
// success
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
// next entry
|
|||
|
pLE = pLE->Flink;
|
|||
|
}
|
|||
|
|
|||
|
// initialize
|
|||
|
*ppQLE = NULL;
|
|||
|
|
|||
|
// failure
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
LoadSubagentData(
|
|||
|
PNETWORK_LIST_ENTRY pNLE,
|
|||
|
PQUERY_LIST_ENTRY pQLE
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Loads data to be passed to the subagent DLL.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pNLE - pointer to network list entry.
|
|||
|
|
|||
|
pQLE - pointer to current query.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Returns true if successful.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PLIST_ENTRY pLE;
|
|||
|
PVARBIND_LIST_ENTRY pVLE;
|
|||
|
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_VERBOSE,
|
|||
|
"SNMP: SVC: query 0x%08lx loading.\n", pQLE
|
|||
|
));
|
|||
|
|
|||
|
// attempt to allocate varbind list
|
|||
|
pQLE->SubagentVbl.list = SnmpUtilMemAlloc(
|
|||
|
pQLE->nSubagentVbs * sizeof(SnmpVarBind)
|
|||
|
);
|
|||
|
|
|||
|
// validate varbind list pointer
|
|||
|
if (pQLE->SubagentVbl.list != NULL) {
|
|||
|
|
|||
|
// point to first varbind
|
|||
|
pLE = pQLE->SubagentVbs.Flink;
|
|||
|
|
|||
|
// process each outgoing varbind
|
|||
|
while (pLE != &pQLE->SubagentVbs) {
|
|||
|
|
|||
|
// retrieve pointer to varbind entry from query link
|
|||
|
pVLE = CONTAINING_RECORD(pLE, VARBIND_LIST_ENTRY, QueryLink);
|
|||
|
|
|||
|
// transfer varbind
|
|||
|
SnmpUtilVarBindCpy(
|
|||
|
&pQLE->SubagentVbl.list[pQLE->SubagentVbl.len++],
|
|||
|
&pVLE->ResolvedVb
|
|||
|
);
|
|||
|
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_VERBOSE,
|
|||
|
"SNMP: SVC: variable %d copied to query 0x%08lx.\n",
|
|||
|
pVLE->nErrorIndex,
|
|||
|
pQLE
|
|||
|
));
|
|||
|
|
|||
|
// next entry
|
|||
|
pLE = pLE->Flink;
|
|||
|
}
|
|||
|
|
|||
|
// create copy of context in case subagent mucks with it
|
|||
|
SnmpUtilOctetsCpy(&pQLE->ContextInfo, &pNLE->Community);
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_ERROR,
|
|||
|
"SNMP: SVC: could not allocate varbind list.\n"
|
|||
|
));
|
|||
|
|
|||
|
// failure
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
// success
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
UnloadSubagentData(
|
|||
|
PQUERY_LIST_ENTRY pQLE
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Unloads data passed to the subagent DLL.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pQLE - pointer to current query.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Returns true if successful.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
__try {
|
|||
|
|
|||
|
// release subagent varbind list
|
|||
|
SnmpUtilVarBindListFree(&pQLE->SubagentVbl);
|
|||
|
|
|||
|
// release subagent context information
|
|||
|
SnmpUtilOctetsFree(&pQLE->ContextInfo);
|
|||
|
|
|||
|
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
|||
|
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_ERROR,
|
|||
|
"SNMP: SVC: exception 0x%08lx processing structure from %s.\n",
|
|||
|
GetExceptionCode(),
|
|||
|
(pQLE->pSLE != NULL)
|
|||
|
? pQLE->pSLE->pPathname
|
|||
|
: "<unknown>"
|
|||
|
));
|
|||
|
|
|||
|
// failure
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
// success
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
UpdateResolvedVarBind(
|
|||
|
PQUERY_LIST_ENTRY pQLE,
|
|||
|
PVARBIND_LIST_ENTRY pVLE,
|
|||
|
UINT iVb
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Updates resolved varbind with data from subagent DLL.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pQLE - pointer to current query.
|
|||
|
|
|||
|
pVLE - pointer to varbind.
|
|||
|
|
|||
|
iVb - index of varbind.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Returns true if successful.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
// see if this is non-repeater
|
|||
|
if (pVLE->nMaxRepetitions == 1) {
|
|||
|
|
|||
|
// flag varbind as resolved
|
|||
|
pVLE->nState = VARBIND_RESOLVED;
|
|||
|
|
|||
|
// release memory for current varbind
|
|||
|
SnmpUtilVarBindFree(&pVLE->ResolvedVb);
|
|||
|
|
|||
|
// transfer varbind from subagent
|
|||
|
SnmpUtilVarBindCpy(&pVLE->ResolvedVb,
|
|||
|
&pQLE->SubagentVbl.list[iVb]
|
|||
|
);
|
|||
|
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_VERBOSE,
|
|||
|
"SNMP: SVC: variable %d name %s.\n",
|
|||
|
pVLE->nErrorIndex,
|
|||
|
SnmpUtilOidToA(&pVLE->ResolvedVb.name)
|
|||
|
));
|
|||
|
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_VERBOSE,
|
|||
|
"SNMP: SVC: variable %d state '%s'.\n",
|
|||
|
pVLE->nErrorIndex,
|
|||
|
VARBINDSTATESTRING(pVLE->nState)
|
|||
|
));
|
|||
|
|
|||
|
// success
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
// see if varbind list allocated
|
|||
|
if ((pVLE->ResolvedVbl.len == 0) &&
|
|||
|
(pVLE->ResolvedVbl.list == NULL)) {
|
|||
|
|
|||
|
// allocate varbind list to fill in
|
|||
|
pVLE->ResolvedVbl.list = SnmpUtilMemAlloc(
|
|||
|
pVLE->nMaxRepetitions *
|
|||
|
sizeof(SnmpVarBind)
|
|||
|
);
|
|||
|
// validate pointer before continuing
|
|||
|
if (pVLE->ResolvedVbl.list == NULL) {
|
|||
|
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_ERROR,
|
|||
|
"SNMP: SVC: could not allocate new varbinds.\n"
|
|||
|
));
|
|||
|
|
|||
|
// failure
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// release working varbind name
|
|||
|
SnmpUtilOidFree(&pVLE->ResolvedVb.name);
|
|||
|
|
|||
|
// transfer name for next iteration
|
|||
|
SnmpUtilOidCpy(&pVLE->ResolvedVb.name,
|
|||
|
&pQLE->SubagentVbl.list[iVb].name
|
|||
|
);
|
|||
|
|
|||
|
// transfer varbind
|
|||
|
SnmpUtilVarBindCpy(
|
|||
|
&pVLE->ResolvedVbl.list[pVLE->ResolvedVbl.len],
|
|||
|
&pQLE->SubagentVbl.list[iVb]
|
|||
|
);
|
|||
|
|
|||
|
// increment count
|
|||
|
pVLE->ResolvedVbl.len++;
|
|||
|
|
|||
|
// see if this is the last varbind to retrieve
|
|||
|
pVLE->nState = (pVLE->nMaxRepetitions > pVLE->ResolvedVbl.len)
|
|||
|
? VARBIND_PARTIALLY_RESOLVED
|
|||
|
: VARBIND_RESOLVED
|
|||
|
;
|
|||
|
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_VERBOSE,
|
|||
|
"SNMP: SVC: variable %d name %s.\n",
|
|||
|
pVLE->nErrorIndex,
|
|||
|
SnmpUtilOidToA(&pVLE->ResolvedVb.name)
|
|||
|
));
|
|||
|
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_VERBOSE,
|
|||
|
"SNMP: SVC: variable %d state '%s'.\n",
|
|||
|
pVLE->nErrorIndex,
|
|||
|
VARBINDSTATESTRING(pVLE->nState)
|
|||
|
));
|
|||
|
|
|||
|
// success
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
UpdateVarBind(
|
|||
|
PNETWORK_LIST_ENTRY pNLE,
|
|||
|
PQUERY_LIST_ENTRY pQLE,
|
|||
|
PVARBIND_LIST_ENTRY pVLE,
|
|||
|
UINT iVb
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Updates varbind with data from subagent DLL.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pNLE - pointer to network list entry.
|
|||
|
|
|||
|
pQLE - pointer to current query.
|
|||
|
|
|||
|
pVLE - pointer to varbind.
|
|||
|
|
|||
|
iVb - index of varbind.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Returns true if successful.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PLIST_ENTRY pLE;
|
|||
|
INT nDiff1;
|
|||
|
INT nDiff2;
|
|||
|
|
|||
|
__try {
|
|||
|
|
|||
|
// determine order of returned varbind
|
|||
|
nDiff1 = SnmpUtilOidCmp(&pQLE->SubagentVbl.list[iVb].name,
|
|||
|
&pVLE->ResolvedVb.name
|
|||
|
);
|
|||
|
|
|||
|
// see if this is getnext or getbulk
|
|||
|
if ((pNLE->Pdu.nType == SNMP_PDU_GETNEXT) ||
|
|||
|
(pNLE->Pdu.nType == SNMP_PDU_GETBULK)) {
|
|||
|
|
|||
|
// determine whether returned varbind in range
|
|||
|
nDiff2 = SnmpUtilOidCmp(&pQLE->SubagentVbl.list[iVb].name,
|
|||
|
&pVLE->pCurrentRLE->LimitOid
|
|||
|
);
|
|||
|
|
|||
|
// make sure returned oid in range
|
|||
|
if ((nDiff1 > 0) && (nDiff2 < 0)) {
|
|||
|
|
|||
|
// update resolved variable binding
|
|||
|
return UpdateResolvedVarBind(pQLE, pVLE, iVb);
|
|||
|
|
|||
|
} else if (nDiff2 >= 0) {
|
|||
|
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_VERBOSE,
|
|||
|
"SNMP: SVC: %s received getnext request for %s.\n",
|
|||
|
pQLE->pSLE->pPathname,
|
|||
|
SnmpUtilOidToA(&pVLE->ResolvedVb.name)
|
|||
|
));
|
|||
|
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_VERBOSE,
|
|||
|
"SNMP: SVC: %s returned out-of-range oid %s.\n",
|
|||
|
pQLE->pSLE->pPathname,
|
|||
|
SnmpUtilOidToA(&pQLE->SubagentVbl.list[iVb].name)
|
|||
|
));
|
|||
|
|
|||
|
// retrieve pointer to next region
|
|||
|
pLE = pVLE->pCurrentRLE->Link.Flink;
|
|||
|
|
|||
|
// see if we exhausted regions
|
|||
|
if (pLE != &g_SupportedRegions) {
|
|||
|
|
|||
|
PMIB_REGION_LIST_ENTRY pNextRLE;
|
|||
|
|
|||
|
// retrieve pointer to mib region
|
|||
|
pNextRLE = CONTAINING_RECORD(pLE,
|
|||
|
MIB_REGION_LIST_ENTRY,
|
|||
|
Link
|
|||
|
);
|
|||
|
|
|||
|
// see if next region supported by same subagent
|
|||
|
if (pVLE->pCurrentRLE->pSLE == pNextRLE->pSLE) {
|
|||
|
|
|||
|
BOOL retCode;
|
|||
|
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_TRACE,
|
|||
|
"SNMP: SVC: next region also supported by %s.\n",
|
|||
|
pVLE->pCurrentRLE->pSLE->pPathname
|
|||
|
));
|
|||
|
|
|||
|
// update resolved variable binding
|
|||
|
retCode = UpdateResolvedVarBind(pQLE, pVLE, iVb);
|
|||
|
if (pQLE->SubagentVbl.list[iVb].value.asnType != ASN_NULL)
|
|||
|
{
|
|||
|
return retCode;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// point to next region
|
|||
|
pVLE->pCurrentRLE = pNextRLE;
|
|||
|
|
|||
|
// change state to partially resolved
|
|||
|
pVLE->nState = VARBIND_PARTIALLY_RESOLVED;
|
|||
|
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_VERBOSE,
|
|||
|
"SNMP: SVC: variable %d state '%s'.\n",
|
|||
|
pVLE->nErrorIndex,
|
|||
|
VARBINDSTATESTRING(pVLE->nState)
|
|||
|
));
|
|||
|
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_TRACE,
|
|||
|
"SNMP: SVC: variable %d re-assigned to %s.\n",
|
|||
|
pVLE->nErrorIndex,
|
|||
|
pVLE->pCurrentRLE->pSLE->pPathname
|
|||
|
));
|
|||
|
}
|
|||
|
|
|||
|
else if ((pVLE->ResolvedVbl.len == 0) &&
|
|||
|
(pVLE->ResolvedVbl.list == NULL)) {
|
|||
|
|
|||
|
// flag varbind as resolved
|
|||
|
pVLE->nState = VARBIND_RESOLVED;
|
|||
|
|
|||
|
// set default varbind to eomv
|
|||
|
pVLE->ResolvedVb.value.asnType =
|
|||
|
SNMP_EXCEPTION_ENDOFMIBVIEW;
|
|||
|
|
|||
|
// update error status counter for the operation
|
|||
|
mgmtCTick(CsnmpOutNoSuchNames);
|
|||
|
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_VERBOSE,
|
|||
|
"SNMP: SVC: variable %d state '%s'.\n",
|
|||
|
pVLE->nErrorIndex,
|
|||
|
VARBINDSTATESTRING(pVLE->nState)
|
|||
|
));
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
// flag varbind as resolved
|
|||
|
pVLE->nState = VARBIND_RESOLVED;
|
|||
|
|
|||
|
// transfer name
|
|||
|
SnmpUtilOidCpy(
|
|||
|
&pVLE->ResolvedVbl.list[pVLE->ResolvedVbl.len].name,
|
|||
|
&pVLE->ResolvedVb.name
|
|||
|
);
|
|||
|
|
|||
|
// set current varbind to eomv
|
|||
|
pVLE->ResolvedVbl.list[pVLE->ResolvedVbl.len].value.asnType =
|
|||
|
SNMP_EXCEPTION_ENDOFMIBVIEW;
|
|||
|
|
|||
|
// increment count
|
|||
|
pVLE->ResolvedVbl.len++;
|
|||
|
|
|||
|
// update error status counter for the operation
|
|||
|
mgmtCTick(CsnmpOutNoSuchNames);
|
|||
|
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_VERBOSE,
|
|||
|
"SNMP: SVC: variable %d state '%s'.\n",
|
|||
|
pVLE->nErrorIndex,
|
|||
|
VARBINDSTATESTRING(pVLE->nState)
|
|||
|
));
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_ERROR,
|
|||
|
"SNMP: SVC: %s received getnext request for %s.\n",
|
|||
|
pQLE->pSLE->pPathname,
|
|||
|
SnmpUtilOidToA(&pVLE->ResolvedVb.name)
|
|||
|
));
|
|||
|
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_ERROR,
|
|||
|
"SNMP: SVC: %s returned invalid oid %s.\n",
|
|||
|
pQLE->pSLE->pPathname,
|
|||
|
SnmpUtilOidToA(&pQLE->SubagentVbl.list[iVb].name)
|
|||
|
));
|
|||
|
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_ERROR,
|
|||
|
"SNMP: SVC: Ban %s subagent, forward the request to a different one.\n",
|
|||
|
pQLE->pSLE->pPathname
|
|||
|
));
|
|||
|
|
|||
|
// trying to forward this getnext request to the next region but only if not handled
|
|||
|
// by the same subagent!
|
|||
|
pLE = pVLE->pCurrentRLE->Link.Flink;
|
|||
|
while( pLE != &g_SupportedRegions)
|
|||
|
{
|
|||
|
PMIB_REGION_LIST_ENTRY pNextRLE;
|
|||
|
|
|||
|
// retrieve pointer to mib region
|
|||
|
pNextRLE = CONTAINING_RECORD(pLE,
|
|||
|
MIB_REGION_LIST_ENTRY,
|
|||
|
Link
|
|||
|
);
|
|||
|
|
|||
|
// if this 'next' region is handled by the same subagent, skip to the next!
|
|||
|
if (pVLE->pCurrentRLE->pSLE == pNextRLE->pSLE)
|
|||
|
{
|
|||
|
pLE = pNextRLE->Link.Flink;
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
// ok, we have one, forward the original GetNext request to it
|
|||
|
pVLE->pCurrentRLE = pNextRLE;
|
|||
|
pVLE->nState = VARBIND_PARTIALLY_RESOLVED;
|
|||
|
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_TRACE,
|
|||
|
"SNMP: SVC: variable %d re-assigned to %s.\n",
|
|||
|
pVLE->nErrorIndex,
|
|||
|
pVLE->pCurrentRLE->pSLE->pPathname
|
|||
|
));
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
// failure
|
|||
|
// here I should emulate a (NO_SUCH_NAME) EndOfMibView, resolve the variable and return TRUE.
|
|||
|
pVLE->nState = VARBIND_RESOLVED;
|
|||
|
pVLE->ResolvedVb.value.asnType = SNMP_EXCEPTION_ENDOFMIBVIEW;
|
|||
|
pVLE->pCurrentRLE = NULL;
|
|||
|
|
|||
|
// update error status counter
|
|||
|
mgmtCTick(CsnmpOutNoSuchNames);
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
} else if (pNLE->Pdu.nType == SNMP_PDU_GET) {
|
|||
|
|
|||
|
// must match
|
|||
|
if (nDiff1 == 0) {
|
|||
|
|
|||
|
// flag varbind as resolved
|
|||
|
pVLE->nState = VARBIND_RESOLVED;
|
|||
|
|
|||
|
// release memory for current varbind
|
|||
|
SnmpUtilVarBindFree(&pVLE->ResolvedVb);
|
|||
|
|
|||
|
// transfer varbind from subagent
|
|||
|
SnmpUtilVarBindCpy(&pVLE->ResolvedVb,
|
|||
|
&pQLE->SubagentVbl.list[iVb]
|
|||
|
);
|
|||
|
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_VERBOSE,
|
|||
|
"SNMP: SVC: variable %d name %s.\n",
|
|||
|
pVLE->nErrorIndex,
|
|||
|
SnmpUtilOidToA(&pVLE->ResolvedVb.name)
|
|||
|
));
|
|||
|
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_VERBOSE,
|
|||
|
"SNMP: SVC: variable %d state '%s'.\n",
|
|||
|
pVLE->nErrorIndex,
|
|||
|
VARBINDSTATESTRING(pVLE->nState)
|
|||
|
));
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_ERROR,
|
|||
|
"SNMP: SVC: %s received get request for %s.\n",
|
|||
|
pQLE->pSLE->pPathname,
|
|||
|
SnmpUtilOidToA(&pVLE->ResolvedVb.name)
|
|||
|
));
|
|||
|
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_ERROR,
|
|||
|
"SNMP: SVC: %s returned invalid oid %s.\n",
|
|||
|
pQLE->pSLE->pPathname,
|
|||
|
SnmpUtilOidToA(&pQLE->SubagentVbl.list[iVb].name)
|
|||
|
));
|
|||
|
|
|||
|
// failure
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
} else if (nDiff1 != 0) {
|
|||
|
// set request failed -> invalid oid
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_ERROR,
|
|||
|
"SNMP: SVC: %s received set request for %s.\n",
|
|||
|
pQLE->pSLE->pPathname,
|
|||
|
SnmpUtilOidToA(&pVLE->ResolvedVb.name)
|
|||
|
));
|
|||
|
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_ERROR,
|
|||
|
"SNMP: SVC: %s returned invalid oid %s.\n",
|
|||
|
pQLE->pSLE->pPathname,
|
|||
|
SnmpUtilOidToA(&pQLE->SubagentVbl.list[iVb].name)
|
|||
|
));
|
|||
|
|
|||
|
// failure
|
|||
|
return FALSE;
|
|||
|
} else {
|
|||
|
|
|||
|
// set request, oids match
|
|||
|
// WARNING!! - state might be set prematurely on SET_TEST / SET_CLEANUP
|
|||
|
pVLE->nState = VARBIND_RESOLVED;
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
|||
|
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_ERROR,
|
|||
|
"SNMP: SVC: exception 0x%08lx processing structure from %s.\n",
|
|||
|
GetExceptionCode(),
|
|||
|
pQLE->pSLE->pPathname
|
|||
|
));
|
|||
|
|
|||
|
// failure
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
// success
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
UpdateVarBinds(
|
|||
|
PNETWORK_LIST_ENTRY pNLE,
|
|||
|
PQUERY_LIST_ENTRY pQLE
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Updates varbind list entries with data from subagent DLL.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pNLE - pointer to network list entry.
|
|||
|
|
|||
|
pQLE - pointer to current query.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Returns true if successful.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PLIST_ENTRY pLE;
|
|||
|
PVARBIND_LIST_ENTRY pVLE;
|
|||
|
BOOL fOk = TRUE;
|
|||
|
UINT iVb = 0;
|
|||
|
|
|||
|
// point to first varbind
|
|||
|
pLE = pQLE->SubagentVbs.Flink;
|
|||
|
|
|||
|
// see if error encountered during callback
|
|||
|
if (pQLE->nErrorStatus == SNMP_ERRORSTATUS_NOERROR) {
|
|||
|
|
|||
|
// process each outgoing varbind
|
|||
|
while (pLE != &pQLE->SubagentVbs) {
|
|||
|
|
|||
|
// retrieve pointer to varbind entry from query link
|
|||
|
pVLE = CONTAINING_RECORD(pLE, VARBIND_LIST_ENTRY, QueryLink);
|
|||
|
|
|||
|
// update individual varbind
|
|||
|
if (!UpdateVarBind(pNLE, pQLE, pVLE, iVb++)) {
|
|||
|
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_ERROR,
|
|||
|
"SNMP: SVC: variable %d could not be updated.\n",
|
|||
|
pQLE->nErrorIndex
|
|||
|
));
|
|||
|
|
|||
|
// update pdu with the proper varbind error index
|
|||
|
pNLE->Pdu.Pdu.NormPdu.nErrorStatus = SNMP_ERRORSTATUS_GENERR;
|
|||
|
pNLE->Pdu.Pdu.NormPdu.nErrorIndex = pVLE->nErrorIndex;
|
|||
|
|
|||
|
// failure
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
// next entry
|
|||
|
pLE = pLE->Flink;
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_VERBOSE,
|
|||
|
"SNMP: SVC: searching for errant variable.\n"
|
|||
|
));
|
|||
|
|
|||
|
// update pdu with status returned from subagent
|
|||
|
pNLE->Pdu.Pdu.NormPdu.nErrorStatus = pQLE->nErrorStatus;
|
|||
|
|
|||
|
// process each outgoing varbind
|
|||
|
while (pLE != &pQLE->SubagentVbs) {
|
|||
|
|
|||
|
// retrieve pointer to varbind entry from query link
|
|||
|
pVLE = CONTAINING_RECORD(pLE, VARBIND_LIST_ENTRY, QueryLink);
|
|||
|
|
|||
|
// see if errant varbind nErrorIndex is starts from 1 !!
|
|||
|
if (pQLE->nErrorIndex == ++iVb) {
|
|||
|
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_TRACE,
|
|||
|
"SNMP: SVC: variable %d involved in failure.\n",
|
|||
|
pVLE->nErrorIndex
|
|||
|
));
|
|||
|
|
|||
|
// update pdu with the proper varbind error index
|
|||
|
pNLE->Pdu.Pdu.NormPdu.nErrorIndex = pVLE->nErrorIndex;
|
|||
|
|
|||
|
// the error code was successfully identified
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
// next entry
|
|||
|
pLE = pLE->Flink;
|
|||
|
}
|
|||
|
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_TRACE,
|
|||
|
"SNMP: SVC: no variable involved in failure.\n"
|
|||
|
));
|
|||
|
|
|||
|
// failure
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
// success
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
CallSubagent(
|
|||
|
PQUERY_LIST_ENTRY pQLE,
|
|||
|
UINT nRequestType,
|
|||
|
UINT nTransactionId
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
Invokes method from subagent DLL.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pNLE - pointer to network list entry.
|
|||
|
|
|||
|
nRequestType - type of request to post to subagent.
|
|||
|
|
|||
|
nTransactionId - identifies snmp pdu sent from manager.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Returns true if successful.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
BOOL fOk = FALSE;
|
|||
|
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_VERBOSE,
|
|||
|
"SNMP: SVC: --- query %s begin ---\n",
|
|||
|
pQLE->pSLE->pPathname
|
|||
|
));
|
|||
|
|
|||
|
__try {
|
|||
|
|
|||
|
// determine which version of query supported
|
|||
|
if (pQLE->pSLE->pfnSnmpExtensionQueryEx != NULL) {
|
|||
|
|
|||
|
// process query using new interface
|
|||
|
fOk = (*pQLE->pSLE->pfnSnmpExtensionQueryEx)(
|
|||
|
nRequestType,
|
|||
|
nTransactionId,
|
|||
|
&pQLE->SubagentVbl,
|
|||
|
&pQLE->ContextInfo,
|
|||
|
&pQLE->nErrorStatus,
|
|||
|
&pQLE->nErrorIndex
|
|||
|
);
|
|||
|
|
|||
|
// see if query is actually valid for downlevel call
|
|||
|
} else if ((pQLE->pSLE->pfnSnmpExtensionQuery != NULL) &&
|
|||
|
((nRequestType == SNMP_EXTENSION_GET) ||
|
|||
|
(nRequestType == SNMP_EXTENSION_GET_NEXT) ||
|
|||
|
(nRequestType == SNMP_EXTENSION_SET_COMMIT))) {
|
|||
|
|
|||
|
// process query using old interface
|
|||
|
fOk = (*pQLE->pSLE->pfnSnmpExtensionQuery)(
|
|||
|
(BYTE)(UINT)nRequestType,
|
|||
|
&pQLE->SubagentVbl,
|
|||
|
&pQLE->nErrorStatus,
|
|||
|
&pQLE->nErrorIndex
|
|||
|
);
|
|||
|
|
|||
|
// see if query can be completed successfully anyway
|
|||
|
} else if ((nRequestType == SNMP_EXTENSION_SET_TEST) ||
|
|||
|
(nRequestType == SNMP_EXTENSION_SET_CLEANUP)) {
|
|||
|
|
|||
|
// fake it
|
|||
|
fOk = TRUE;
|
|||
|
}
|
|||
|
|
|||
|
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
|||
|
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_ERROR,
|
|||
|
"SNMP: SVC: exception 0x%08lx calling %s.\n",
|
|||
|
GetExceptionCode(),
|
|||
|
pQLE->pSLE->pPathname
|
|||
|
));
|
|||
|
}
|
|||
|
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_VERBOSE,
|
|||
|
"SNMP: SVC: --- query %s end ---\n",
|
|||
|
pQLE->pSLE->pPathname
|
|||
|
));
|
|||
|
|
|||
|
// validate
|
|||
|
if (!fOk) {
|
|||
|
|
|||
|
// identify failing subagent
|
|||
|
pQLE->nErrorStatus = SNMP_ERRORSTATUS_GENERR;
|
|||
|
pQLE->nErrorIndex = 1;
|
|||
|
|
|||
|
} else if (pQLE->nErrorStatus != SNMP_ERRORSTATUS_NOERROR) {
|
|||
|
|
|||
|
// see if error index needs to be adjusted
|
|||
|
if ((pQLE->nErrorIndex > pQLE->nSubagentVbs) ||
|
|||
|
(pQLE->nErrorIndex == 0)) {
|
|||
|
|
|||
|
// set to first varbind
|
|||
|
pQLE->nErrorIndex = 1;
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
// re-initialize
|
|||
|
pQLE->nErrorIndex = 0;
|
|||
|
}
|
|||
|
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_VERBOSE,
|
|||
|
"SNMP: SVC: query 0x%08lx %s, errorStatus=%s, errorIndex=%d.\n",
|
|||
|
pQLE,
|
|||
|
(pQLE->nErrorStatus == SNMP_ERRORSTATUS_NOERROR)
|
|||
|
? "succeeded"
|
|||
|
: "failed"
|
|||
|
,
|
|||
|
SNMPERRORSTRING(pQLE->nErrorStatus),
|
|||
|
pQLE->nErrorIndex
|
|||
|
));
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
ProcessSet(
|
|||
|
PNETWORK_LIST_ENTRY pNLE
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Processes SNMP_PDU_SET requests.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pNLE - pointer to network list entry.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Returns true if successful.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PLIST_ENTRY pLE = NULL;
|
|||
|
PQUERY_LIST_ENTRY pQLE;
|
|||
|
BOOL fOk = TRUE;
|
|||
|
|
|||
|
// load subagent queries
|
|||
|
if (!LoadQueries(pNLE)) {
|
|||
|
|
|||
|
// unload immediately
|
|||
|
UnloadQueries(pNLE);
|
|||
|
|
|||
|
// failure
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
// point to first query
|
|||
|
pLE = pNLE->Queries.Flink;
|
|||
|
|
|||
|
// process each subagent query
|
|||
|
while (fOk && (pLE != &pNLE->Queries)) {
|
|||
|
|
|||
|
// retrieve pointer to query entry from link
|
|||
|
pQLE = CONTAINING_RECORD(pLE, QUERY_LIST_ENTRY, Link);
|
|||
|
|
|||
|
// load outgoing varbinds
|
|||
|
fOk = LoadSubagentData(pNLE, pQLE);
|
|||
|
|
|||
|
// validate
|
|||
|
if (fOk) {
|
|||
|
|
|||
|
// dispatch
|
|||
|
CallSubagent(
|
|||
|
pQLE,
|
|||
|
SNMP_EXTENSION_SET_TEST,
|
|||
|
pNLE->nTransactionId
|
|||
|
);
|
|||
|
|
|||
|
// process results returned
|
|||
|
fOk = UpdateVarBinds(pNLE, pQLE);
|
|||
|
}
|
|||
|
|
|||
|
// next entry (or reverse direction)
|
|||
|
pLE = fOk ? pLE->Flink : pLE->Blink;
|
|||
|
}
|
|||
|
|
|||
|
// validate
|
|||
|
if (fOk) {
|
|||
|
|
|||
|
// if this line is missing => GenErr on UpdatePdu()
|
|||
|
pLE = pNLE->Queries.Flink;
|
|||
|
|
|||
|
// process each subagent query
|
|||
|
while (fOk && (pLE != &pNLE->Queries)) {
|
|||
|
|
|||
|
// retrieve pointer to query entry from link
|
|||
|
pQLE = CONTAINING_RECORD(pLE, QUERY_LIST_ENTRY, Link);
|
|||
|
|
|||
|
// dispatch
|
|||
|
CallSubagent(
|
|||
|
pQLE,
|
|||
|
SNMP_EXTENSION_SET_COMMIT,
|
|||
|
pNLE->nTransactionId
|
|||
|
);
|
|||
|
|
|||
|
// process results returned
|
|||
|
fOk = UpdateVarBinds(pNLE, pQLE);
|
|||
|
|
|||
|
// next entry (or reverse direction)
|
|||
|
pLE = fOk ? pLE->Flink : pLE->Blink;
|
|||
|
}
|
|||
|
|
|||
|
// validate
|
|||
|
if (!fOk) {
|
|||
|
|
|||
|
// process each subagent query
|
|||
|
while (pLE != &pNLE->Queries) {
|
|||
|
|
|||
|
// retrieve pointer to query entry from link
|
|||
|
pQLE = CONTAINING_RECORD(pLE, QUERY_LIST_ENTRY, Link);
|
|||
|
|
|||
|
// dispatch
|
|||
|
CallSubagent(
|
|||
|
pQLE,
|
|||
|
SNMP_EXTENSION_SET_UNDO,
|
|||
|
pNLE->nTransactionId
|
|||
|
);
|
|||
|
|
|||
|
// process results returned
|
|||
|
UpdateVarBinds(pNLE, pQLE);
|
|||
|
|
|||
|
// previous entry
|
|||
|
pLE = pLE->Blink;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// point to last query
|
|||
|
pLE = pNLE->Queries.Blink;
|
|||
|
}
|
|||
|
|
|||
|
// process each subagent query
|
|||
|
while (pLE != &pNLE->Queries) {
|
|||
|
|
|||
|
// retrieve pointer to query entry from link
|
|||
|
pQLE = CONTAINING_RECORD(pLE, QUERY_LIST_ENTRY, Link);
|
|||
|
|
|||
|
// dispatch
|
|||
|
CallSubagent(
|
|||
|
pQLE,
|
|||
|
SNMP_EXTENSION_SET_CLEANUP,
|
|||
|
pNLE->nTransactionId
|
|||
|
);
|
|||
|
|
|||
|
// process results returned
|
|||
|
UpdateVarBinds(pNLE, pQLE);
|
|||
|
|
|||
|
// previous entry
|
|||
|
pLE = pLE->Blink;
|
|||
|
}
|
|||
|
|
|||
|
// cleanup queries
|
|||
|
UnloadQueries(pNLE);
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
ProcessGet(
|
|||
|
PNETWORK_LIST_ENTRY pNLE
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Queries subagents to resolve varbinds.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pNLE - pointer to network list entry.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Returns true if successful.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PLIST_ENTRY pLE;
|
|||
|
PQUERY_LIST_ENTRY pQLE = NULL;
|
|||
|
BOOL fOk = TRUE;
|
|||
|
|
|||
|
// load subagent queries
|
|||
|
if (!LoadQueries(pNLE)) {
|
|||
|
|
|||
|
// unload immediately
|
|||
|
UnloadQueries(pNLE);
|
|||
|
|
|||
|
// failure
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
|
|||
|
// point to first query
|
|||
|
pLE = pNLE->Queries.Flink;
|
|||
|
|
|||
|
// process each subagent query
|
|||
|
while (fOk && (pLE != &pNLE->Queries)) {
|
|||
|
|
|||
|
// retrieve pointer to query entry from link
|
|||
|
pQLE = CONTAINING_RECORD(pLE, QUERY_LIST_ENTRY, Link);
|
|||
|
|
|||
|
// load outgoing varbinds
|
|||
|
fOk = LoadSubagentData(pNLE, pQLE);
|
|||
|
|
|||
|
// validate
|
|||
|
if (fOk) {
|
|||
|
|
|||
|
// dispatch
|
|||
|
CallSubagent(
|
|||
|
pQLE,
|
|||
|
SNMP_EXTENSION_GET,
|
|||
|
pNLE->nTransactionId
|
|||
|
);
|
|||
|
|
|||
|
// process results returned
|
|||
|
fOk = UpdateVarBinds(pNLE, pQLE);
|
|||
|
}
|
|||
|
|
|||
|
// next entry
|
|||
|
pLE = pLE->Flink;
|
|||
|
}
|
|||
|
|
|||
|
// cleanup queries
|
|||
|
UnloadQueries(pNLE);
|
|||
|
|
|||
|
return fOk;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
ProcessGetBulk(
|
|||
|
PNETWORK_LIST_ENTRY pNLE
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Queries subagents to resolve varbinds.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pNLE - pointer to network list entry.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Returns true if successful.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PLIST_ENTRY pLE;
|
|||
|
PQUERY_LIST_ENTRY pQLE = NULL;
|
|||
|
BOOL fOk = TRUE;
|
|||
|
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_VERBOSE,
|
|||
|
"SNMP: SVC: getbulk request, non-repeaters %d, max-repetitions %d.\n",
|
|||
|
pNLE->Pdu.Pdu.BulkPdu.nNonRepeaters,
|
|||
|
pNLE->Pdu.Pdu.BulkPdu.nMaxRepetitions
|
|||
|
));
|
|||
|
|
|||
|
// loop
|
|||
|
while (fOk) {
|
|||
|
|
|||
|
// load subagent queries
|
|||
|
fOk = LoadQueries(pNLE);
|
|||
|
|
|||
|
// validate
|
|||
|
if (fOk && !IsListEmpty(&pNLE->Queries)) {
|
|||
|
|
|||
|
// point to first query
|
|||
|
pLE = pNLE->Queries.Flink;
|
|||
|
|
|||
|
// process each subagent query
|
|||
|
while (fOk && (pLE != &pNLE->Queries)) {
|
|||
|
|
|||
|
// retrieve pointer to query entry from link
|
|||
|
pQLE = CONTAINING_RECORD(pLE, QUERY_LIST_ENTRY, Link);
|
|||
|
|
|||
|
// load outgoing varbinds
|
|||
|
fOk = LoadSubagentData(pNLE, pQLE);
|
|||
|
|
|||
|
// validate
|
|||
|
if (fOk) {
|
|||
|
|
|||
|
// dispatch
|
|||
|
CallSubagent(
|
|||
|
pQLE,
|
|||
|
SNMP_EXTENSION_GET_NEXT,
|
|||
|
pNLE->nTransactionId
|
|||
|
);
|
|||
|
|
|||
|
// process results returned
|
|||
|
fOk = UpdateVarBinds(pNLE, pQLE);
|
|||
|
}
|
|||
|
|
|||
|
// next entry
|
|||
|
pLE = pLE->Flink;
|
|||
|
}
|
|||
|
|
|||
|
} else if (IsListEmpty(&pNLE->Queries)) {
|
|||
|
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_VERBOSE,
|
|||
|
"SNMP: SVC: no more queries to process.\n"
|
|||
|
));
|
|||
|
|
|||
|
break; // finished...
|
|||
|
}
|
|||
|
|
|||
|
// cleanup queries
|
|||
|
UnloadQueries(pNLE);
|
|||
|
}
|
|||
|
|
|||
|
return fOk;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
///////////////////////////////////////////////////////////////////////////////
|
|||
|
// //
|
|||
|
// Public procedures //
|
|||
|
// //
|
|||
|
///////////////////////////////////////////////////////////////////////////////
|
|||
|
|
|||
|
BOOL
|
|||
|
AllocQLE(
|
|||
|
PQUERY_LIST_ENTRY * ppQLE
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Allocates query list entry.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
ppQLE - pointer to receive list entry pointer.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Returns true if successful.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
BOOL fOk = FALSE;
|
|||
|
PQUERY_LIST_ENTRY pQLE = NULL;
|
|||
|
|
|||
|
// attempt to allocate structure
|
|||
|
pQLE = AgentMemAlloc(sizeof(QUERY_LIST_ENTRY));
|
|||
|
|
|||
|
// validate
|
|||
|
if (pQLE != NULL) {
|
|||
|
|
|||
|
// initialize outgoing varbind list
|
|||
|
InitializeListHead(&pQLE->SubagentVbs);
|
|||
|
|
|||
|
// success
|
|||
|
fOk = TRUE;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_ERROR,
|
|||
|
"SNMP: SVC: could not allocate query.\n"
|
|||
|
));
|
|||
|
}
|
|||
|
|
|||
|
// transfer
|
|||
|
*ppQLE = pQLE;
|
|||
|
|
|||
|
return fOk;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
FreeQLE(
|
|||
|
PQUERY_LIST_ENTRY pQLE
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Creates queries from varbind list entries.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pNLE - pointer to network list entry with SNMP message.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Returns true if successful.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
// validate pointer
|
|||
|
if (pQLE != NULL) {
|
|||
|
|
|||
|
// release subagent info
|
|||
|
UnloadSubagentData(pQLE);
|
|||
|
|
|||
|
// release structure
|
|||
|
AgentMemFree(pQLE);
|
|||
|
}
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
LoadQueries(
|
|||
|
PNETWORK_LIST_ENTRY pNLE
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Creates queries from varbind list entries.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pNLE - pointer to network list entry.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Returns true if successful.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PLIST_ENTRY pLE;
|
|||
|
PVARBIND_LIST_ENTRY pVLE;
|
|||
|
PQUERY_LIST_ENTRY pQLE = NULL;
|
|||
|
|
|||
|
// point to first varbind
|
|||
|
pLE = pNLE->Bindings.Flink;
|
|||
|
|
|||
|
// process each binding
|
|||
|
while (pLE != &pNLE->Bindings) {
|
|||
|
|
|||
|
// retrieve pointer to varbind entry from link
|
|||
|
pVLE = CONTAINING_RECORD(pLE, VARBIND_LIST_ENTRY, Link);
|
|||
|
|
|||
|
// analyze current state of varbind
|
|||
|
if ((pVLE->nState == VARBIND_INITIALIZED) ||
|
|||
|
(pVLE->nState == VARBIND_PARTIALLY_RESOLVED)) {
|
|||
|
|
|||
|
// attempt to locate existing query
|
|||
|
if (FindQueryBySLE(&pQLE, pNLE, pVLE->pCurrentRLE->pSLE)) {
|
|||
|
|
|||
|
// attach varbind entry to query via query link
|
|||
|
InsertTailList(&pQLE->SubagentVbs, &pVLE->QueryLink);
|
|||
|
|
|||
|
// change varbind state
|
|||
|
pVLE->nState = VARBIND_RESOLVING;
|
|||
|
|
|||
|
// increment total
|
|||
|
pQLE->nSubagentVbs++;
|
|||
|
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_VERBOSE,
|
|||
|
"SNMP: SVC: variable %d added to existing query 0x%08lx.\n",
|
|||
|
pVLE->nErrorIndex,
|
|||
|
pQLE
|
|||
|
));
|
|||
|
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_VERBOSE,
|
|||
|
"SNMP: SVC: variable %d state '%s'.\n",
|
|||
|
pVLE->nErrorIndex,
|
|||
|
VARBINDSTATESTRING(pVLE->nState)
|
|||
|
));
|
|||
|
|
|||
|
// attempt to allocate entry
|
|||
|
} else if (AllocQLE(&pQLE)) {
|
|||
|
|
|||
|
// obtain subagent pointer
|
|||
|
pQLE->pSLE = pVLE->pCurrentRLE->pSLE;
|
|||
|
|
|||
|
// insert into query list
|
|||
|
InsertTailList(&pNLE->Queries, &pQLE->Link);
|
|||
|
|
|||
|
// attach varbind entry to query via query link
|
|||
|
InsertTailList(&pQLE->SubagentVbs, &pVLE->QueryLink);
|
|||
|
|
|||
|
// change varbind state
|
|||
|
pVLE->nState = VARBIND_RESOLVING;
|
|||
|
|
|||
|
// increment total
|
|||
|
pQLE->nSubagentVbs++;
|
|||
|
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_VERBOSE,
|
|||
|
"SNMP: SVC: variable %d added to new query 0x%08lx.\n",
|
|||
|
pVLE->nErrorIndex,
|
|||
|
pQLE
|
|||
|
));
|
|||
|
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_VERBOSE,
|
|||
|
"SNMP: SVC: variable %d state '%s'.\n",
|
|||
|
pVLE->nErrorIndex,
|
|||
|
VARBINDSTATESTRING(pVLE->nState)
|
|||
|
));
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
SNMPDBG((
|
|||
|
SNMP_LOG_ERROR,
|
|||
|
"SNMP: SVC: could not contruct query.\n"
|
|||
|
));
|
|||
|
|
|||
|
// failure
|
|||
|
return FALSE;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// next entry
|
|||
|
pLE = pLE->Flink;
|
|||
|
}
|
|||
|
|
|||
|
// success
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
UnloadQueries(
|
|||
|
PNETWORK_LIST_ENTRY pNLE
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Destroys queries from varbind list entries.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pNLE - pointer to network list entry with SNMP message.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Returns true if successful.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
PLIST_ENTRY pLE;
|
|||
|
PQUERY_LIST_ENTRY pQLE;
|
|||
|
|
|||
|
// process each query entry
|
|||
|
while (!IsListEmpty(&pNLE->Queries)) {
|
|||
|
|
|||
|
// point to first query
|
|||
|
pLE = RemoveHeadList(&pNLE->Queries);
|
|||
|
|
|||
|
// retrieve pointer to query from link
|
|||
|
pQLE = CONTAINING_RECORD(pLE, QUERY_LIST_ENTRY, Link);
|
|||
|
|
|||
|
// release
|
|||
|
FreeQLE(pQLE);
|
|||
|
}
|
|||
|
|
|||
|
return TRUE;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
BOOL
|
|||
|
ProcessQueries(
|
|||
|
PNETWORK_LIST_ENTRY pNLE
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Queries subagents to resolve varbinds.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
pNLE - pointer to network list entry.
|
|||
|
|
|||
|
Return Values:
|
|||
|
|
|||
|
Returns true if successful.
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
// determine pdu
|
|||
|
switch (pNLE->Pdu.nType) {
|
|||
|
|
|||
|
case SNMP_PDU_GETNEXT:
|
|||
|
case SNMP_PDU_GETBULK:
|
|||
|
|
|||
|
// multiple non-exact reads
|
|||
|
return ProcessGetBulk(pNLE);
|
|||
|
|
|||
|
case SNMP_PDU_GET:
|
|||
|
|
|||
|
// single exact read
|
|||
|
return ProcessGet(pNLE);
|
|||
|
|
|||
|
case SNMP_PDU_SET:
|
|||
|
|
|||
|
// single exact write
|
|||
|
return ProcessSet(pNLE);
|
|||
|
}
|
|||
|
|
|||
|
// failure
|
|||
|
return FALSE;
|
|||
|
}
|