952 lines
23 KiB
C
952 lines
23 KiB
C
/*++
|
||
|
||
Copyright (c) 1992-1997 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
varbinds.c
|
||
|
||
Abstract:
|
||
|
||
Contains routines for manipulating varbinds.
|
||
|
||
Environment:
|
||
|
||
User Mode - Win32
|
||
|
||
Revision History:
|
||
|
||
10-Feb-1997 DonRyan
|
||
Rewrote to implement SNMPv2 support.
|
||
|
||
--*/
|
||
|
||
///////////////////////////////////////////////////////////////////////////////
|
||
// //
|
||
// Include files //
|
||
// //
|
||
///////////////////////////////////////////////////////////////////////////////
|
||
|
||
#include "globals.h"
|
||
#include "varbinds.h"
|
||
#include "query.h"
|
||
#include "snmpmgmt.h"
|
||
|
||
|
||
///////////////////////////////////////////////////////////////////////////////
|
||
// //
|
||
// Private procedures //
|
||
// //
|
||
///////////////////////////////////////////////////////////////////////////////
|
||
|
||
BOOL
|
||
LoadVarBind(
|
||
PNETWORK_LIST_ENTRY pNLE,
|
||
UINT iVb
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Creates varbind list entry from varbind structure.
|
||
|
||
Arguments:
|
||
|
||
pNLE - pointer to network list entry.
|
||
|
||
iVb - index of variable binding.
|
||
|
||
Return Values:
|
||
|
||
Returns true if successful.
|
||
|
||
--*/
|
||
|
||
{
|
||
SnmpVarBind * pVb;
|
||
PVARBIND_LIST_ENTRY pVLE = NULL;
|
||
PMIB_REGION_LIST_ENTRY pRLE = NULL;
|
||
BOOL fAnyOk;
|
||
BOOL fOk;
|
||
|
||
// allocate list entry
|
||
if (fOk = AllocVLE(&pVLE)) {
|
||
|
||
// save varbind list index
|
||
pVLE->nErrorIndex = iVb + 1;
|
||
|
||
// retrieve varbind pointer
|
||
pVb = &pNLE->Pdu.Vbl.list[iVb];
|
||
|
||
SNMPDBG((
|
||
SNMP_LOG_TRACE,
|
||
"SNMP: SVC: variable %d name %s.\n",
|
||
pVLE->nErrorIndex,
|
||
SnmpUtilOidToA(&pVb->name)
|
||
));
|
||
|
||
// initialize type of resolved variable
|
||
pVLE->ResolvedVb.value.asnType = ASN_NULL;
|
||
|
||
// copy varbind name to working structure
|
||
SnmpUtilOidCpy(&pVLE->ResolvedVb.name, &pVb->name);
|
||
|
||
// see if specific object asked for
|
||
fAnyOk = ((pNLE->Pdu.nType == SNMP_PDU_GETNEXT) ||
|
||
(pNLE->Pdu.nType == SNMP_PDU_GETBULK));
|
||
|
||
// attempt to lookup variable name in supported regions
|
||
if (FindSupportedRegion(&pRLE, &pVb->name, fAnyOk)) {
|
||
|
||
// save pointer to region
|
||
pVLE->pCurrentRLE = pRLE;
|
||
|
||
// structure has been initialized
|
||
pVLE->nState = VARBIND_INITIALIZED;
|
||
|
||
SNMPDBG((
|
||
SNMP_LOG_TRACE,
|
||
"SNMP: SVC: variable %d assigned to %s.\n",
|
||
pVLE->nErrorIndex,
|
||
pVLE->pCurrentRLE->pSLE->pPathname
|
||
));
|
||
|
||
SNMPDBG((
|
||
SNMP_LOG_VERBOSE,
|
||
"SNMP: SVC: variable %d state '%s'.\n",
|
||
pVLE->nErrorIndex,
|
||
VARBINDSTATESTRING(pVLE->nState)
|
||
));
|
||
|
||
// see if this is a getnext request
|
||
if (pNLE->Pdu.nType == SNMP_PDU_GETNEXT) {
|
||
|
||
// only need single rep
|
||
pVLE->nMaxRepetitions = 1;
|
||
|
||
} else if (pNLE->Pdu.nType == SNMP_PDU_GETBULK) {
|
||
|
||
// see if this non-repeater which is in bounds
|
||
if (pNLE->Pdu.Pdu.BulkPdu.nNonRepeaters > (int)iVb) {
|
||
|
||
// only need single rep
|
||
pVLE->nMaxRepetitions = 1;
|
||
|
||
SNMPDBG((
|
||
SNMP_LOG_VERBOSE,
|
||
"SNMP: SVC: variable %d max repetitions %d.\n",
|
||
pVLE->nErrorIndex,
|
||
pVLE->nMaxRepetitions
|
||
));
|
||
|
||
// see if max-repetitions is non-zero
|
||
} else if (pNLE->Pdu.Pdu.BulkPdu.nMaxRepetitions > 0) {
|
||
|
||
// set max-repetitions to value in getbulk pdu
|
||
pVLE->nMaxRepetitions = pNLE->Pdu.Pdu.BulkPdu.nMaxRepetitions;
|
||
|
||
SNMPDBG((
|
||
SNMP_LOG_VERBOSE,
|
||
"SNMP: SVC: variable %d max repetitions %d.\n",
|
||
pVLE->nErrorIndex,
|
||
pVLE->nMaxRepetitions
|
||
));
|
||
|
||
} else {
|
||
|
||
// modify state to resolved
|
||
pVLE->nState = VARBIND_RESOLVED;
|
||
|
||
SNMPDBG((
|
||
SNMP_LOG_VERBOSE,
|
||
"SNMP: SVC: variable %d state '%s'.\n",
|
||
pVLE->nErrorIndex,
|
||
VARBINDSTATESTRING(pVLE->nState)
|
||
));
|
||
|
||
SNMPDBG((
|
||
SNMP_LOG_VERBOSE,
|
||
"SNMP: SVC: variable %d value NULL.\n",
|
||
pVLE->nErrorIndex
|
||
));
|
||
}
|
||
|
||
} else if (pNLE->Pdu.nType == SNMP_PDU_SET) {
|
||
|
||
// copy varbind value to working structure
|
||
SnmpUtilAsnAnyCpy(&pVLE->ResolvedVb.value, &pVb->value);
|
||
|
||
SNMPDBG((
|
||
SNMP_LOG_VERBOSE,
|
||
"SNMP: SVC: variable %d value %s.\n",
|
||
pVLE->nErrorIndex,
|
||
"<TBD>"
|
||
));
|
||
}
|
||
|
||
} else {
|
||
|
||
// null pointer to region
|
||
pVLE->pCurrentRLE = NULL;
|
||
|
||
SNMPDBG((
|
||
SNMP_LOG_TRACE,
|
||
"SNMP: SVC: variable %d unable to be assigned.\n",
|
||
pVLE->nErrorIndex
|
||
));
|
||
|
||
// getbulk
|
||
if (fAnyOk) {
|
||
|
||
// modify state to resolved
|
||
pVLE->nState = VARBIND_RESOLVED;
|
||
|
||
// set the exception in the variable's type field
|
||
pVLE->ResolvedVb.value.asnType = SNMP_EXCEPTION_ENDOFMIBVIEW;
|
||
|
||
SNMPDBG((
|
||
SNMP_LOG_VERBOSE,
|
||
"SNMP: SVC: variable %d state '%s'.\n",
|
||
pVLE->nErrorIndex,
|
||
VARBINDSTATESTRING(pVLE->nState)
|
||
));
|
||
|
||
SNMPDBG((
|
||
SNMP_LOG_VERBOSE,
|
||
"SNMP: SVC: variable %d value ENDOFMIBVIEW.\n",
|
||
pVLE->nErrorIndex
|
||
));
|
||
|
||
} else if (pNLE->Pdu.nType == SNMP_PDU_GET) {
|
||
|
||
// modify state to resolved
|
||
pVLE->nState = VARBIND_RESOLVED;
|
||
|
||
// set the exception in the variable's type field
|
||
pVLE->ResolvedVb.value.asnType = SNMP_EXCEPTION_NOSUCHOBJECT;
|
||
|
||
SNMPDBG((
|
||
SNMP_LOG_VERBOSE,
|
||
"SNMP: SVC: variable %d state '%s'.\n",
|
||
pVLE->nErrorIndex,
|
||
VARBINDSTATESTRING(pVLE->nState)
|
||
));
|
||
|
||
SNMPDBG((
|
||
SNMP_LOG_VERBOSE,
|
||
"SNMP: SVC: variable %d value NOSUCHOBJECT.\n",
|
||
pVLE->nErrorIndex
|
||
));
|
||
|
||
} else {
|
||
|
||
// modify state to resolved
|
||
//pVLE->nState = VARBIND_ABORTED;
|
||
pVLE->nState = VARBIND_RESOLVED;
|
||
|
||
// save error status in network list entry
|
||
pNLE->Pdu.Pdu.NormPdu.nErrorStatus = SNMP_ERRORSTATUS_NOTWRITABLE;
|
||
pNLE->Pdu.Pdu.NormPdu.nErrorIndex = pVLE->nErrorIndex;
|
||
|
||
SNMPDBG((
|
||
SNMP_LOG_VERBOSE,
|
||
"SNMP: SVC: variable %d state '%s'.\n",
|
||
pVLE->nErrorIndex,
|
||
VARBINDSTATESTRING(pVLE->nState)
|
||
));
|
||
|
||
SNMPDBG((
|
||
SNMP_LOG_VERBOSE,
|
||
"SNMP: SVC: variable %d error %s.\n",
|
||
pVLE->nErrorIndex,
|
||
SNMPERRORSTRING(pNLE->Pdu.Pdu.NormPdu.nErrorStatus)
|
||
));
|
||
|
||
// failure
|
||
//fOk = FALSE;
|
||
}
|
||
}
|
||
|
||
// add to existing varbind list
|
||
InsertTailList(&pNLE->Bindings, &pVLE->Link);
|
||
}
|
||
|
||
return fOk;
|
||
}
|
||
|
||
|
||
BOOL
|
||
LoadVarBinds(
|
||
PNETWORK_LIST_ENTRY pNLE
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Creates list of varbind entries from varbind structure.
|
||
|
||
Arguments:
|
||
|
||
pNLE - pointer to network list entry.
|
||
|
||
Return Values:
|
||
|
||
Returns true if successful.
|
||
|
||
--*/
|
||
|
||
{
|
||
UINT iVb;
|
||
BOOL fOk = TRUE;
|
||
|
||
// process each varbind in list
|
||
for (iVb = 0; (fOk && (iVb < pNLE->Pdu.Vbl.len)); iVb++) {
|
||
|
||
// load individual varbind
|
||
fOk = LoadVarBind(pNLE, iVb);
|
||
}
|
||
|
||
return fOk;
|
||
}
|
||
|
||
|
||
BOOL
|
||
UnloadVarBinds(
|
||
PNETWORK_LIST_ENTRY pNLE
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Destroys list of varbind entries.
|
||
|
||
Arguments:
|
||
|
||
pNLE - pointer to network list entry.
|
||
|
||
Return Values:
|
||
|
||
Returns true if successful.
|
||
|
||
--*/
|
||
|
||
{
|
||
PLIST_ENTRY pLE;
|
||
PVARBIND_LIST_ENTRY pVLE;
|
||
|
||
// process each varbind entry
|
||
while (!IsListEmpty(&pNLE->Bindings)) {
|
||
|
||
// point to first varbind
|
||
pLE = RemoveHeadList(&pNLE->Bindings);
|
||
|
||
// retrieve pointer to varbind entry from link
|
||
pVLE = CONTAINING_RECORD(pLE, VARBIND_LIST_ENTRY, Link);
|
||
|
||
// release
|
||
FreeVLE(pVLE);
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
BOOL
|
||
ValidateVarBinds(
|
||
PNETWORK_LIST_ENTRY pNLE
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Updates error status based on query results and version.
|
||
|
||
Arguments:
|
||
|
||
pNLE - pointer to network list entry.
|
||
|
||
Return Values:
|
||
|
||
Returns true if successful.
|
||
|
||
--*/
|
||
|
||
{
|
||
PLIST_ENTRY pLE;
|
||
PVARBIND_LIST_ENTRY pVLE;
|
||
|
||
// see if error has already report during processing
|
||
if (pNLE->Pdu.Pdu.NormPdu.nErrorStatus == SNMP_ERRORSTATUS_NOERROR) {
|
||
|
||
// point to first varbind
|
||
pLE = pNLE->Bindings.Flink;
|
||
|
||
// process each varbind entry
|
||
while (pLE != &pNLE->Bindings) {
|
||
|
||
// retrieve pointer to varbind entry from link
|
||
pVLE = CONTAINING_RECORD(pLE, VARBIND_LIST_ENTRY, Link);
|
||
|
||
// see if varbind has been resolved
|
||
if (pVLE->nState != VARBIND_RESOLVED) {
|
||
|
||
SNMPDBG((
|
||
SNMP_LOG_WARNING,
|
||
"SNMP: SVC: variable %d unresolved.\n",
|
||
pVLE->nErrorIndex
|
||
));
|
||
|
||
// report internal error has occurred
|
||
pNLE->Pdu.Pdu.NormPdu.nErrorStatus = SNMP_ERRORSTATUS_GENERR;
|
||
pNLE->Pdu.Pdu.NormPdu.nErrorIndex = pVLE->nErrorIndex;
|
||
|
||
break; // bail...
|
||
|
||
} else if (pNLE->nVersion == SNMP_VERSION_1) {
|
||
|
||
// report error if exceptions are present instead of values
|
||
if ((pVLE->ResolvedVb.value.asnType == SNMP_EXCEPTION_NOSUCHOBJECT) ||
|
||
(pVLE->ResolvedVb.value.asnType == SNMP_EXCEPTION_NOSUCHINSTANCE) ||
|
||
(pVLE->ResolvedVb.value.asnType == SNMP_EXCEPTION_ENDOFMIBVIEW)) {
|
||
|
||
SNMPDBG((
|
||
SNMP_LOG_WARNING,
|
||
"SNMP: SVC: variable %d unresolved in SNMPv1.\n",
|
||
pVLE->nErrorIndex
|
||
));
|
||
|
||
// report that variable could not be found
|
||
pNLE->Pdu.Pdu.NormPdu.nErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME;
|
||
pNLE->Pdu.Pdu.NormPdu.nErrorIndex = pVLE->nErrorIndex;
|
||
|
||
break; // bail...
|
||
}
|
||
}
|
||
|
||
// next entry
|
||
pLE = pLE->Flink;
|
||
}
|
||
}
|
||
|
||
// see if this is first version
|
||
if (pNLE->nVersion == SNMP_VERSION_1) {
|
||
|
||
// adjust status code
|
||
switch (pNLE->Pdu.Pdu.NormPdu.nErrorStatus) {
|
||
|
||
case SNMP_ERRORSTATUS_NOERROR:
|
||
case SNMP_ERRORSTATUS_TOOBIG:
|
||
case SNMP_ERRORSTATUS_NOSUCHNAME:
|
||
case SNMP_ERRORSTATUS_BADVALUE:
|
||
case SNMP_ERRORSTATUS_READONLY:
|
||
case SNMP_ERRORSTATUS_GENERR:
|
||
break;
|
||
|
||
case SNMP_ERRORSTATUS_NOACCESS:
|
||
case SNMP_ERRORSTATUS_NOCREATION:
|
||
case SNMP_ERRORSTATUS_NOTWRITABLE:
|
||
case SNMP_ERRORSTATUS_AUTHORIZATIONERROR:
|
||
case SNMP_ERRORSTATUS_INCONSISTENTNAME:
|
||
pNLE->Pdu.Pdu.NormPdu.nErrorStatus = SNMP_ERRORSTATUS_NOSUCHNAME;
|
||
break;
|
||
|
||
case SNMP_ERRORSTATUS_WRONGTYPE:
|
||
case SNMP_ERRORSTATUS_WRONGLENGTH:
|
||
case SNMP_ERRORSTATUS_WRONGENCODING:
|
||
case SNMP_ERRORSTATUS_WRONGVALUE:
|
||
case SNMP_ERRORSTATUS_INCONSISTENTVALUE:
|
||
pNLE->Pdu.Pdu.NormPdu.nErrorStatus = SNMP_ERRORSTATUS_BADVALUE;
|
||
break;
|
||
|
||
case SNMP_ERRORSTATUS_RESOURCEUNAVAILABLE:
|
||
case SNMP_ERRORSTATUS_COMMITFAILED:
|
||
case SNMP_ERRORSTATUS_UNDOFAILED:
|
||
default:
|
||
pNLE->Pdu.Pdu.NormPdu.nErrorStatus = SNMP_ERRORSTATUS_GENERR;
|
||
break;
|
||
}
|
||
}
|
||
|
||
return (pNLE->Pdu.Pdu.NormPdu.nErrorStatus == SNMP_ERRORSTATUS_NOERROR);
|
||
}
|
||
|
||
|
||
BOOL
|
||
UpdateVarBindsFromResolvedVb(
|
||
PNETWORK_LIST_ENTRY pNLE
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Updates varbinds with results containing single varbinds.
|
||
|
||
Arguments:
|
||
|
||
pNLE - pointer to network list entry.
|
||
|
||
Return Values:
|
||
|
||
Returns true if successful.
|
||
|
||
--*/
|
||
|
||
{
|
||
PLIST_ENTRY pLE;
|
||
PVARBIND_LIST_ENTRY pVLE;
|
||
|
||
// point to first varbind
|
||
pLE = pNLE->Bindings.Flink;
|
||
|
||
// process each varbind entry
|
||
while (pLE != &pNLE->Bindings) {
|
||
|
||
// retrieve pointer to varbind entry from link
|
||
pVLE = CONTAINING_RECORD(pLE, VARBIND_LIST_ENTRY, Link);
|
||
|
||
SNMPDBG((
|
||
SNMP_LOG_TRACE,
|
||
"SNMP: SVC: variable %d resolved name %s.\n",
|
||
pVLE->nErrorIndex,
|
||
SnmpUtilOidToA(&pVLE->ResolvedVb.name)
|
||
));
|
||
|
||
// release memory for original varbind
|
||
SnmpUtilVarBindFree(&pNLE->Pdu.Vbl.list[pVLE->nErrorIndex - 1]);
|
||
|
||
// copy resolved varbind structure into pdu varbindlist
|
||
SnmpUtilVarBindCpy(&pNLE->Pdu.Vbl.list[pVLE->nErrorIndex - 1],
|
||
&pVLE->ResolvedVb
|
||
);
|
||
|
||
// next entry
|
||
pLE = pLE->Flink;
|
||
}
|
||
|
||
// success
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
BOOL
|
||
UpdateVarBindsFromResolvedVbl(
|
||
PNETWORK_LIST_ENTRY pNLE
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Updates varbinds with results containing multiple varbinds.
|
||
|
||
Arguments:
|
||
|
||
pNLE - pointer to network list entry.
|
||
|
||
Return Values:
|
||
|
||
Returns true if successful.
|
||
|
||
--*/
|
||
|
||
{
|
||
UINT nRepeaters;
|
||
UINT nNonRepeaters;
|
||
UINT nMaxRepetitions;
|
||
UINT nIterations;
|
||
UINT nVarBindsLast;
|
||
UINT nVarBinds = 0;
|
||
SnmpVarBind * pVarBind;
|
||
PVARBIND_LIST_ENTRY pVLE;
|
||
PLIST_ENTRY pLE1;
|
||
PLIST_ENTRY pLE2;
|
||
|
||
// retrieve getbulk parameters from pdu
|
||
nNonRepeaters = pNLE->Pdu.Pdu.BulkPdu.nNonRepeaters;
|
||
nMaxRepetitions = pNLE->Pdu.Pdu.BulkPdu.nMaxRepetitions;
|
||
nRepeaters = (pNLE->Pdu.Vbl.len >= nNonRepeaters)
|
||
? (pNLE->Pdu.Vbl.len - nNonRepeaters)
|
||
: 0
|
||
;
|
||
|
||
// see if we need to expand size of varbind list
|
||
if ((nRepeaters > 0) && (nMaxRepetitions > 1)) {
|
||
|
||
UINT nMaxVarBinds;
|
||
SnmpVarBind * pVarBinds;
|
||
|
||
// calculate maximum number of varbinds possible
|
||
nMaxVarBinds = nNonRepeaters + (nMaxRepetitions * nRepeaters);
|
||
|
||
// reallocate varbind list to fit maximum
|
||
pVarBinds = SnmpUtilMemReAlloc(pNLE->Pdu.Vbl.list,
|
||
nMaxVarBinds * sizeof(SnmpVarBind)
|
||
);
|
||
|
||
// validate pointer
|
||
if (pVarBinds == NULL) {
|
||
|
||
SNMPDBG((
|
||
SNMP_LOG_ERROR,
|
||
"SNMP: SVC: Could not re-allocate varbind list.\n"
|
||
));
|
||
|
||
return FALSE; // bail...
|
||
}
|
||
|
||
// restore varbind pointer
|
||
pNLE->Pdu.Vbl.list = pVarBinds;
|
||
}
|
||
|
||
// point to first varbind
|
||
pLE1 = pNLE->Bindings.Flink;
|
||
|
||
// process each varbind entry
|
||
while (pLE1 != &pNLE->Bindings) {
|
||
|
||
// retrieve pointer to varbind entry from link
|
||
pVLE = CONTAINING_RECORD(pLE1, VARBIND_LIST_ENTRY, Link);
|
||
|
||
// see if this is non-repeater
|
||
if (pVLE->nMaxRepetitions == 1) {
|
||
|
||
// release memory for original varbind
|
||
SnmpUtilVarBindFree(&pNLE->Pdu.Vbl.list[nVarBinds]);
|
||
|
||
// copy resolved varbind into pdu structure
|
||
SnmpUtilVarBindCpy(&pNLE->Pdu.Vbl.list[nVarBinds++],
|
||
&pVLE->ResolvedVb
|
||
);
|
||
|
||
} else {
|
||
|
||
//
|
||
// finished processing non-repeaters
|
||
//
|
||
|
||
break;
|
||
}
|
||
|
||
// next entry
|
||
pLE1 = pLE1->Flink;
|
||
}
|
||
|
||
// initialize
|
||
nIterations = 0;
|
||
|
||
// store
|
||
pLE2 = pLE1;
|
||
|
||
// process any repeaters until max
|
||
while (nIterations < nMaxRepetitions) {
|
||
|
||
// restore
|
||
pLE1 = pLE2;
|
||
|
||
// process each varbind entry
|
||
while (pLE1 != &pNLE->Bindings) {
|
||
|
||
// retrieve pointer to varbind entry from link
|
||
pVLE = CONTAINING_RECORD(pLE1, VARBIND_LIST_ENTRY, Link);
|
||
|
||
// see if value stored in default
|
||
if (pVLE->ResolvedVbl.len == 0) {
|
||
|
||
// release memory for original varbind
|
||
SnmpUtilVarBindFree(&pNLE->Pdu.Vbl.list[nVarBinds]);
|
||
|
||
// copy resolved varbind into pdu varbind list
|
||
SnmpUtilVarBindCpy(&pNLE->Pdu.Vbl.list[nVarBinds],
|
||
&pVLE->ResolvedVb
|
||
);
|
||
|
||
// increment
|
||
nVarBinds++;
|
||
|
||
// see if value available in this iteration
|
||
} else if (pVLE->ResolvedVbl.len > nIterations) {
|
||
|
||
// release memory for original varbind
|
||
SnmpUtilVarBindFree(&pNLE->Pdu.Vbl.list[nVarBinds]);
|
||
|
||
// copy resolved varbind into pdu varbind list
|
||
SnmpUtilVarBindCpy(&pNLE->Pdu.Vbl.list[nVarBinds],
|
||
&pVLE->ResolvedVbl.list[nIterations]
|
||
);
|
||
|
||
// increment
|
||
nVarBinds++;
|
||
}
|
||
|
||
// next entry
|
||
pLE1 = pLE1->Flink;
|
||
}
|
||
|
||
// increment
|
||
nIterations++;
|
||
}
|
||
|
||
// save new varbind count
|
||
pNLE->Pdu.Vbl.len = nVarBinds;
|
||
|
||
// success
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
BOOL
|
||
UpdatePdu(
|
||
PNETWORK_LIST_ENTRY pNLE,
|
||
BOOL fOk
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Updates pdu with query results.
|
||
|
||
Arguments:
|
||
|
||
pNLE - pointer to network list entry.
|
||
|
||
fOk - true if process succeeded to this point.
|
||
|
||
Return Values:
|
||
|
||
Returns true if successful.
|
||
|
||
--*/
|
||
|
||
{
|
||
PLIST_ENTRY pLE;
|
||
PVARBIND_LIST_ENTRY pVLE;
|
||
|
||
// validate
|
||
if (fOk) {
|
||
|
||
// make sure varbinds valid
|
||
fOk = ValidateVarBinds(pNLE);
|
||
|
||
// validate
|
||
if (fOk) {
|
||
|
||
// see if pdu type is getnext or getbulk
|
||
if (pNLE->Pdu.nType != SNMP_PDU_GETBULK) {
|
||
|
||
// update varbinds with single result
|
||
fOk = UpdateVarBindsFromResolvedVb(pNLE);
|
||
|
||
} else {
|
||
|
||
// update varbinds with multiple results
|
||
fOk = UpdateVarBindsFromResolvedVbl(pNLE);
|
||
}
|
||
}
|
||
}
|
||
|
||
// trap internal errors that have not been accounted for as of yet
|
||
if (!fOk && (pNLE->Pdu.Pdu.NormPdu.nErrorStatus == SNMP_ERRORSTATUS_NOERROR)) {
|
||
|
||
// report status that was determined above
|
||
pNLE->Pdu.Pdu.NormPdu.nErrorStatus = SNMP_ERRORSTATUS_GENERR;
|
||
pNLE->Pdu.Pdu.NormPdu.nErrorIndex = 0;
|
||
}
|
||
|
||
if (pNLE->Pdu.Pdu.NormPdu.nErrorStatus == SNMP_ERRORSTATUS_NOERROR)
|
||
{
|
||
switch(pNLE->Pdu.nType)
|
||
{
|
||
case SNMP_PDU_GETNEXT:
|
||
case SNMP_PDU_GETBULK:
|
||
case SNMP_PDU_GET:
|
||
// update counter for successful GET-NEXT GET-BULK
|
||
mgmtCAdd(CsnmpInTotalReqVars, pNLE->Pdu.Vbl.len);
|
||
break;
|
||
case SNMP_PDU_SET:
|
||
// update counter for successful SET
|
||
mgmtCAdd(CsnmpInTotalSetVars, pNLE->Pdu.Vbl.len);
|
||
break;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// update here counters for all OUT errors
|
||
mgmtUtilUpdateErrStatus(OUT_errStatus, pNLE->Pdu.Pdu.NormPdu.nErrorStatus);
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
///////////////////////////////////////////////////////////////////////////////
|
||
// //
|
||
// Public procedures //
|
||
// //
|
||
///////////////////////////////////////////////////////////////////////////////
|
||
|
||
BOOL
|
||
AllocVLE(
|
||
PVARBIND_LIST_ENTRY * ppVLE
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Allocates varbind structure and initializes.
|
||
|
||
Arguments:
|
||
|
||
ppVLE - pointer to receive pointer to entry.
|
||
|
||
Return Values:
|
||
|
||
Returns true if successful.
|
||
|
||
--*/
|
||
|
||
{
|
||
BOOL fOk = FALSE;
|
||
PVARBIND_LIST_ENTRY pVLE = NULL;
|
||
|
||
// attempt to allocate structure
|
||
pVLE = AgentMemAlloc(sizeof(VARBIND_LIST_ENTRY));
|
||
|
||
// validate
|
||
if (pVLE != NULL) {
|
||
|
||
// success
|
||
fOk = TRUE;
|
||
|
||
} else {
|
||
|
||
SNMPDBG((
|
||
SNMP_LOG_ERROR,
|
||
"SNMP: SVC: could not allocate varbind entry.\n"
|
||
));
|
||
}
|
||
|
||
// transfer
|
||
*ppVLE = pVLE;
|
||
|
||
return fOk;
|
||
}
|
||
|
||
|
||
BOOL
|
||
FreeVLE(
|
||
PVARBIND_LIST_ENTRY pVLE
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Releases varbind structure.
|
||
|
||
Arguments:
|
||
|
||
pVLE - pointer to list entry to be freed.
|
||
|
||
Return Values:
|
||
|
||
Returns true if successful.
|
||
|
||
--*/
|
||
|
||
{
|
||
BOOL fOk = TRUE;
|
||
|
||
// validate pointer
|
||
if (pVLE != NULL) {
|
||
|
||
// release current varbind
|
||
SnmpUtilVarBindFree(&pVLE->ResolvedVb);
|
||
|
||
// release current varbind list
|
||
SnmpUtilVarBindListFree(&pVLE->ResolvedVbl);
|
||
|
||
// release structure
|
||
AgentMemFree(pVLE);
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
BOOL
|
||
ProcessVarBinds(
|
||
PNETWORK_LIST_ENTRY pNLE
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Creates list of varbind entries from varbind structure.
|
||
|
||
Arguments:
|
||
|
||
pNLE - pointer to network list entry.
|
||
|
||
Return Values:
|
||
|
||
Returns true if successful.
|
||
|
||
--*/
|
||
|
||
{
|
||
BOOL fOk = FALSE;
|
||
|
||
// validate type before processing
|
||
if ((pNLE->Pdu.nType == SNMP_PDU_SET) ||
|
||
(pNLE->Pdu.nType == SNMP_PDU_GET) ||
|
||
(pNLE->Pdu.nType == SNMP_PDU_GETNEXT) ||
|
||
(pNLE->Pdu.nType == SNMP_PDU_GETBULK)) {
|
||
|
||
// initialize varbinds
|
||
if (LoadVarBinds(pNLE)) {
|
||
|
||
// process queries
|
||
fOk = ProcessQueries(pNLE);
|
||
}
|
||
|
||
// transfer results
|
||
UpdatePdu(pNLE, fOk);
|
||
|
||
// unload varbinds
|
||
UnloadVarBinds(pNLE);
|
||
|
||
// update management counters for accepted and processed requests
|
||
switch(pNLE->Pdu.nType)
|
||
{
|
||
case SNMP_PDU_GET:
|
||
mgmtCTick(CsnmpInGetRequests);
|
||
break;
|
||
case SNMP_PDU_GETNEXT:
|
||
case SNMP_PDU_GETBULK:
|
||
mgmtCTick(CsnmpInGetNexts);
|
||
break;
|
||
case SNMP_PDU_SET:
|
||
mgmtCTick(CsnmpInSetRequests);
|
||
break;
|
||
}
|
||
|
||
} else {
|
||
|
||
SNMPDBG((
|
||
SNMP_LOG_ERROR,
|
||
"SNMP: SVC: ignoring unknown pdu type %d.\n",
|
||
pNLE->Pdu.nType
|
||
));
|
||
}
|
||
|
||
return fOk;
|
||
}
|