You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
4103 lines
108 KiB
4103 lines
108 KiB
/*++
|
|
|
|
Copyright (c) 1992-1996 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
snmptfx.c
|
|
|
|
Abstract:
|
|
|
|
Provides common varbind resolution functionality for subagents.
|
|
|
|
Environment:
|
|
|
|
User Mode - Win32
|
|
|
|
Revision History:
|
|
|
|
02-Oct-1996 DonRyan
|
|
Moved from extensible agent in anticipation of SNMPv2 SPI.
|
|
|
|
--*/
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// Include files //
|
|
// //
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h> // using ntrtl's ASSERT
|
|
#include <snmp.h>
|
|
#include <snmputil.h>
|
|
#include <snmpexts.h>
|
|
#include <winsock.h>
|
|
|
|
#define HASH_TABLE_SIZE 101
|
|
#define HASH_TABLE_RADIX 18
|
|
|
|
#define INVALID_INDEX ((DWORD)(-1))
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// Private type definitions //
|
|
// //
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
typedef struct _SnmpVarBindXlat {
|
|
|
|
UINT vlIndex; // index into view list
|
|
UINT vblIndex; // index into varbind list
|
|
SnmpMibEntry * mibEntry; // pointer to mib information
|
|
struct _SnmpExtQuery * extQuery; // pointer to followup query
|
|
|
|
|
|
} SnmpVarBindXlat;
|
|
|
|
typedef struct _SnmpGenericList {
|
|
|
|
VOID * data; // context-specific pointer
|
|
UINT len; // context-specific length
|
|
|
|
} SnmpGenericList;
|
|
|
|
typedef struct _SnmpTableXlat {
|
|
|
|
AsnObjectIdentifier txOid; // table index oid
|
|
SnmpMibTable * txInfo; // table description
|
|
UINT txIndex; // index into table list
|
|
|
|
} SnmpTableXlat;
|
|
|
|
typedef struct _SnmpExtQuery {
|
|
|
|
UINT mibAction; // type of query
|
|
UINT viewType; // type of view
|
|
UINT vblNum; // number of varbinds
|
|
SnmpVarBindXlat * vblXlat; // info to reorder varbinds
|
|
SnmpTableXlat * tblXlat; // info to parse table oids
|
|
SnmpGenericList extData; // context-specific buffer
|
|
FARPROC extFunc; // instrumentation callback
|
|
|
|
} SnmpExtQuery;
|
|
|
|
#define INVALID_QUERY ((SnmpExtQuery*)(-1))
|
|
|
|
typedef struct _SnmpExtQueryList {
|
|
|
|
SnmpExtQuery * query; // list of subagent queries
|
|
UINT len; // number of queries in list
|
|
UINT action; // original query request
|
|
|
|
} SnmpExtQueryList;
|
|
|
|
typedef struct _SnmpHashNode {
|
|
|
|
SnmpMibEntry * mibEntry;
|
|
struct _SnmpHashNode * nextEntry;
|
|
|
|
} SnmpHashNode;
|
|
|
|
typedef struct _SnmpTfxView {
|
|
|
|
SnmpMibView * mibView;
|
|
SnmpHashNode ** hashTable;
|
|
|
|
} SnmpTfxView;
|
|
|
|
typedef struct _SnmpTfxInfo {
|
|
|
|
UINT numViews;
|
|
SnmpTfxView * tfxViews;
|
|
|
|
} SnmpTfxInfo;
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// Private prototypes //
|
|
// //
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
VOID
|
|
ValidateQueryList(
|
|
SnmpTfxInfo * tfxInfo,
|
|
SnmpExtQueryList * ql,
|
|
UINT q,
|
|
RFC1157VarBindList * vbl,
|
|
UINT * errorStatus,
|
|
UINT * errorIndex
|
|
);
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// Private procedures //
|
|
// //
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
UINT
|
|
OidToHashTableIndex(
|
|
AsnObjectIdentifier * hashOid
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Hash function for mib entry access.
|
|
|
|
Arguments:
|
|
|
|
hashOid - object identifer to hash into table position.
|
|
|
|
Return Values:
|
|
|
|
Returns hash table position.
|
|
|
|
--*/
|
|
|
|
{
|
|
UINT i;
|
|
UINT j;
|
|
|
|
// process each element of the oid
|
|
for (i=0, j=0; i < hashOid->idLength; i++) {
|
|
|
|
// determine table position by summing oid
|
|
j = (j * HASH_TABLE_RADIX) + hashOid->ids[i];
|
|
}
|
|
|
|
// adjust to within table
|
|
return (j % HASH_TABLE_SIZE);
|
|
}
|
|
|
|
|
|
VOID
|
|
FreeHashTable(
|
|
SnmpHashNode ** hashTable
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Destroys hash table used for accessing views.
|
|
|
|
Arguments:
|
|
|
|
hashTable - table of hash nodes.
|
|
|
|
Return Values:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
UINT i;
|
|
|
|
SnmpHashNode * nextNode;
|
|
SnmpHashNode * hashNode;
|
|
|
|
if (hashTable == NULL) {
|
|
return;
|
|
}
|
|
|
|
// free hash table and nodes
|
|
for (i=0; i < HASH_TABLE_SIZE; i++) {
|
|
|
|
// point to first item
|
|
hashNode = hashTable[i];
|
|
|
|
// find end of node list
|
|
while (hashNode) {
|
|
|
|
// save pointer to next node
|
|
nextNode = hashNode->nextEntry;
|
|
|
|
// free current node
|
|
SnmpUtilMemFree(hashNode);
|
|
|
|
// retrieve next
|
|
hashNode = nextNode;
|
|
}
|
|
}
|
|
|
|
// release table itself
|
|
SnmpUtilMemFree(hashTable);
|
|
}
|
|
|
|
|
|
SnmpHashNode **
|
|
AllocHashTable(
|
|
SnmpMibView * mibView
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Initializes view hash table.
|
|
|
|
Arguments:
|
|
|
|
mibView - mib view information.
|
|
|
|
Return Values:
|
|
|
|
Returns pointer to first entry if successful.
|
|
|
|
--*/
|
|
|
|
{
|
|
UINT i;
|
|
UINT j;
|
|
|
|
UINT numItems;
|
|
BOOL fInitedOk;
|
|
|
|
SnmpMibEntry * mibEntry;
|
|
SnmpHashNode * hashNode;
|
|
SnmpHashNode ** hashTable = NULL;
|
|
|
|
// validate parameter
|
|
if (mibView == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
// determine how many items in view
|
|
numItems = mibView->viewScalars.len;
|
|
|
|
// load the first entry in the view
|
|
mibEntry = mibView->viewScalars.list;
|
|
|
|
// allocate hash table using predefined size
|
|
hashTable = (SnmpHashNode **)SnmpUtilMemAlloc(
|
|
HASH_TABLE_SIZE * sizeof(SnmpHashNode *)
|
|
);
|
|
|
|
// make sure table is allocated
|
|
fInitedOk = (hashTable != NULL);
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: TFX: initializing hash table 0x%08lx (%d items).\n",
|
|
hashTable,
|
|
numItems
|
|
));
|
|
|
|
// process each item in the subagent's supported view
|
|
for (i = 0; (i < numItems) && fInitedOk; i++, mibEntry++) {
|
|
|
|
// hash into table index
|
|
j = OidToHashTableIndex(&mibEntry->mibOid);
|
|
|
|
// check if table entry taken
|
|
if (hashTable[j] == NULL) {
|
|
|
|
// allocate new node
|
|
hashNode = (SnmpHashNode *)SnmpUtilMemAlloc(
|
|
sizeof(SnmpHashNode)
|
|
);
|
|
|
|
// save hash node
|
|
hashTable[j] = hashNode;
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: TFX: adding hash node 0x%08lx to empty slot %d (0x%08lx).\n",
|
|
hashNode, j, mibEntry
|
|
));
|
|
|
|
} else {
|
|
|
|
// point to first item
|
|
hashNode = hashTable[j];
|
|
|
|
// find end of node list
|
|
while (hashNode->nextEntry) {
|
|
hashNode = hashNode->nextEntry;
|
|
}
|
|
|
|
// allocate new node entry
|
|
hashNode->nextEntry = (SnmpHashNode *)SnmpUtilMemAlloc(
|
|
sizeof(SnmpHashNode)
|
|
);
|
|
|
|
// re-init node to edit below
|
|
hashNode = hashNode->nextEntry;
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: TFX: adding hash node 0x%08lx to full slot %d (0x%08lx).\n",
|
|
hashNode, j, mibEntry
|
|
));
|
|
}
|
|
|
|
// make sure allocation succeeded
|
|
fInitedOk = (hashNode != NULL);
|
|
|
|
if (fInitedOk) {
|
|
|
|
// fill in node values
|
|
hashNode->mibEntry = mibEntry;
|
|
}
|
|
}
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: TFX: %s initialized hash table 0x%08lx.\n",
|
|
fInitedOk ? "successfully" : "unsuccessfully",
|
|
hashTable
|
|
));
|
|
|
|
if (!fInitedOk) {
|
|
|
|
// free view hash table
|
|
FreeHashTable(hashTable);
|
|
|
|
// reinitialize
|
|
hashTable = NULL;
|
|
}
|
|
|
|
return hashTable;
|
|
}
|
|
|
|
|
|
VOID
|
|
OidToMibEntry(
|
|
AsnObjectIdentifier * hashOid,
|
|
SnmpHashNode ** hashTable,
|
|
SnmpMibEntry ** mibEntry
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Returns mib entry associated with given object identifier.
|
|
|
|
Arguments:
|
|
|
|
hashOid - oid to convert to table index.
|
|
hashTable - table to look up entry.
|
|
mibEntry - pointer to mib entry information.
|
|
|
|
Return Values:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
UINT i;
|
|
SnmpHashNode * hashNode;
|
|
AsnObjectIdentifier newOid;
|
|
|
|
// create index
|
|
i = OidToHashTableIndex(hashOid);
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: TFX: searching hash table 0x%08lx slot %d for %s.\n",
|
|
hashTable, i, SnmpUtilOidToA(hashOid)
|
|
));
|
|
|
|
// retrieve node
|
|
hashNode = hashTable[i];
|
|
|
|
// initialize
|
|
*mibEntry = NULL;
|
|
|
|
// search list
|
|
while (hashNode) {
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: TFX: searching hash node 0x%08lx (mibe=0x%08lx) - %s.\n",
|
|
hashNode, hashNode->mibEntry,
|
|
SnmpUtilOidToA(&hashNode->mibEntry->mibOid)
|
|
));
|
|
|
|
// retrieve mib identifier
|
|
newOid = hashNode->mibEntry->mibOid;
|
|
|
|
// make sure that the oid matches
|
|
if (!SnmpUtilOidCmp(&newOid, hashOid)) {
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: TFX: returning mib entry 0x%08lx.\n",
|
|
hashNode->mibEntry
|
|
));
|
|
|
|
// return node data
|
|
*mibEntry = hashNode->mibEntry;
|
|
return;
|
|
|
|
}
|
|
|
|
// check next node
|
|
hashNode = hashNode->nextEntry;
|
|
}
|
|
}
|
|
|
|
|
|
int
|
|
ValidateInstanceIdentifier(
|
|
AsnObjectIdentifier * indexOid,
|
|
SnmpMibTable * tableInfo
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Validates that oid can be successfully parsed into index entries.
|
|
|
|
Arguments:
|
|
|
|
indexOid - object indentifier of potential index.
|
|
tableInfo - information describing conceptual table.
|
|
|
|
Return Values:
|
|
|
|
Returns the comparision between the length of the indexOid
|
|
and the cumulated lengths of all the indices of the table tableInfo.
|
|
{-1, 0, 1}
|
|
|
|
--*/
|
|
|
|
{
|
|
UINT i = 0;
|
|
UINT j = 0;
|
|
|
|
int nComp;
|
|
|
|
BOOL fFixed;
|
|
BOOL fLimit;
|
|
BOOL fIndex;
|
|
|
|
SnmpMibEntry * mibEntry;
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: TFX: validating index %s via table 0x%08lx.\n",
|
|
SnmpUtilOidToA(indexOid), tableInfo
|
|
));
|
|
|
|
// see if the table indices are specified
|
|
fIndex = (tableInfo->tableIndices != NULL);
|
|
|
|
// scan mib entries of table indices ensuring match of given oid
|
|
for (i = 0; (i < tableInfo->numIndices) && (j < indexOid->idLength); i++) {
|
|
|
|
// get mib entry from table or directly
|
|
mibEntry = fIndex ? tableInfo->tableIndices[i]
|
|
: &tableInfo->tableEntry[i+1]
|
|
;
|
|
|
|
// determine type
|
|
switch (mibEntry->mibType) {
|
|
|
|
// variable length types
|
|
case ASN_OBJECTIDENTIFIER:
|
|
case ASN_RFC1155_OPAQUE:
|
|
case ASN_OCTETSTRING:
|
|
|
|
// check whether this is a fixed length variable or not
|
|
fLimit = (mibEntry->mibMinimum || mibEntry->mibMaximum);
|
|
fFixed = (fLimit && (mibEntry->mibMinimum == mibEntry->mibMaximum));
|
|
|
|
// validate
|
|
if (fFixed) {
|
|
|
|
// increment fixed length
|
|
j += mibEntry->mibMaximum;
|
|
|
|
} else if (fLimit) {
|
|
|
|
// check whether the length of the variable is valid
|
|
if (((INT)indexOid->ids[j] >= mibEntry->mibMinimum) &&
|
|
((INT)indexOid->ids[j] <= mibEntry->mibMaximum)) {
|
|
|
|
// increment given length
|
|
j += (indexOid->ids[j] + 1);
|
|
|
|
} else {
|
|
|
|
// invalidate
|
|
j = INVALID_INDEX;
|
|
}
|
|
|
|
} else {
|
|
|
|
// increment given length
|
|
j += (indexOid->ids[j] + 1);
|
|
}
|
|
|
|
break;
|
|
|
|
// implicit fixed size
|
|
case ASN_RFC1155_IPADDRESS:
|
|
// increment
|
|
j += 4;
|
|
break;
|
|
|
|
case ASN_RFC1155_COUNTER:
|
|
case ASN_RFC1155_GAUGE:
|
|
case ASN_RFC1155_TIMETICKS:
|
|
case ASN_INTEGER:
|
|
// increment
|
|
j++;
|
|
break;
|
|
|
|
default:
|
|
// invalidate
|
|
j = INVALID_INDEX;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i<tableInfo->numIndices)
|
|
nComp = -1;
|
|
else if (j < indexOid->idLength)
|
|
nComp = 1;
|
|
else if (j > indexOid->idLength)
|
|
nComp = -1;
|
|
else
|
|
nComp = 0;
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: TFX: ValidateInstanceIdentifier; OID %s %s table indices.\n",
|
|
SnmpUtilOidToA(indexOid),
|
|
nComp > 0 ? "over-covers" : nComp < 0 ? "shorter than" : "matches"
|
|
));
|
|
|
|
return nComp;
|
|
}
|
|
|
|
|
|
VOID
|
|
ValidateAsnAny(
|
|
AsnAny * asnAny,
|
|
SnmpMibEntry * mibEntry,
|
|
UINT mibAction,
|
|
UINT * errorStatus
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Validates asn value with given mib entry.
|
|
|
|
Arguments:
|
|
|
|
asnAny - value to set.
|
|
mibEntry - mib information.
|
|
mibAction - mib action to be taken.
|
|
errorStatus - used to indicate success or failure.
|
|
|
|
Return Values:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
BOOL fLimit;
|
|
BOOL fFixed;
|
|
|
|
INT asnLen;
|
|
|
|
BOOL fOk = TRUE;
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: TFX: validating value for %s request using entry 0x%08lx.\n",
|
|
(mibAction == MIB_ACTION_SET) ? "write" : "read", mibEntry
|
|
));
|
|
|
|
// validating gets is trivial
|
|
if (mibAction != MIB_ACTION_SET) {
|
|
|
|
// validate instrumentation info
|
|
if ((mibEntry->mibGetBufLen == 0) ||
|
|
(mibEntry->mibGetFunc == NULL) ||
|
|
!(mibEntry->mibAccess & MIB_ACCESS_READ)) {
|
|
|
|
// variable is not available for reading
|
|
*errorStatus = SNMP_ERRORSTATUS_NOSUCHNAME;
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: TFX: entry 0x%08lx not read-enabled.\n",
|
|
mibEntry
|
|
));
|
|
|
|
return; // bail...
|
|
}
|
|
|
|
} else {
|
|
|
|
// validate instrumentation info
|
|
if ((mibEntry->mibSetBufLen == 0) ||
|
|
(mibEntry->mibSetFunc == NULL) ||
|
|
!(mibEntry->mibAccess & MIB_ACCESS_WRITE)) {
|
|
|
|
// variable is not avaiLable for writing
|
|
*errorStatus = SNMP_ERRORSTATUS_NOTWRITABLE;
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: TFX: entry 0x%08lx not write-enabled.\n",
|
|
mibEntry
|
|
));
|
|
|
|
return; // bail...
|
|
}
|
|
|
|
if (mibEntry->mibType != asnAny->asnType)
|
|
{
|
|
*errorStatus = SNMP_ERRORSTATUS_BADVALUE;
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: TFX: entry 0x%08lx doesn't match the asnType",
|
|
mibEntry));
|
|
|
|
return; // bail...
|
|
}
|
|
|
|
// check whether this is a fixed length variable or not
|
|
fLimit = (mibEntry->mibMinimum || mibEntry->mibMaximum);
|
|
fFixed = (fLimit && (mibEntry->mibMinimum == mibEntry->mibMaximum));
|
|
|
|
// determine value type
|
|
switch (asnAny->asnType) {
|
|
|
|
// variable length types
|
|
case ASN_OBJECTIDENTIFIER:
|
|
|
|
// retrieve the objects id length
|
|
asnLen = asnAny->asnValue.object.idLength;
|
|
|
|
// fixed?
|
|
if (fFixed) {
|
|
|
|
// make sure the length is correct
|
|
fOk = (asnLen == mibEntry->mibMaximum);
|
|
|
|
} else if (fLimit) {
|
|
|
|
// make sure the length is correct
|
|
fOk = ((asnLen >= mibEntry->mibMinimum) &&
|
|
(asnLen <= mibEntry->mibMaximum));
|
|
}
|
|
|
|
break;
|
|
|
|
case ASN_RFC1155_OPAQUE:
|
|
case ASN_OCTETSTRING:
|
|
|
|
// retrieve the arbitrary length
|
|
asnLen = asnAny->asnValue.string.length;
|
|
|
|
// fixed?
|
|
if (fFixed) {
|
|
|
|
// make sure the length is correct
|
|
fOk = (asnLen == mibEntry->mibMaximum);
|
|
|
|
} else if (fLimit) {
|
|
|
|
// make sure the length is correct
|
|
fOk = ((asnLen >= mibEntry->mibMinimum) &&
|
|
(asnLen <= mibEntry->mibMaximum));
|
|
}
|
|
|
|
break;
|
|
|
|
case ASN_RFC1155_IPADDRESS:
|
|
|
|
// make sure the length is correct
|
|
fOk = (asnAny->asnValue.address.length == 4);
|
|
break;
|
|
|
|
case ASN_INTEGER:
|
|
|
|
// limited?
|
|
if (fLimit) {
|
|
|
|
// make sure the value in range
|
|
fOk = ((asnAny->asnValue.number >= mibEntry->mibMinimum) &&
|
|
(asnAny->asnValue.number <= mibEntry->mibMaximum));
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
// error...
|
|
fOk = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: TFX: value is %s using entry 0x%08lx.\n",
|
|
fOk ? "valid" : "invalid", mibEntry
|
|
));
|
|
|
|
// report results
|
|
*errorStatus = fOk
|
|
? SNMP_ERRORSTATUS_NOERROR
|
|
: SNMP_ERRORSTATUS_BADVALUE
|
|
;
|
|
}
|
|
|
|
|
|
VOID
|
|
FindMibEntry(
|
|
SnmpTfxInfo * tfxInfo,
|
|
RFC1157VarBind * vb,
|
|
SnmpMibEntry ** mibEntry,
|
|
UINT * mibAction,
|
|
SnmpTableXlat ** tblXlat,
|
|
UINT vlIndex,
|
|
UINT * errorStatus
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Locates mib entry associated with given varbind.
|
|
|
|
Arguments:
|
|
|
|
tfxInfo - context info.
|
|
vb - variable to locate.
|
|
mibEntry - mib entry information.
|
|
mibAction - mib action (may be updated).
|
|
tblXlat - table translation info.
|
|
vlIndex - index into view list.
|
|
errorStatus - used to indicate success or failure.
|
|
|
|
Return Values:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
UINT i;
|
|
UINT j;
|
|
|
|
UINT newIndex;
|
|
UINT numItems;
|
|
UINT numTables;
|
|
|
|
BOOL fFoundOk;
|
|
int indexComp;
|
|
|
|
AsnObjectIdentifier hashOid;
|
|
AsnObjectIdentifier indexOid;
|
|
AsnObjectIdentifier * viewOid;
|
|
|
|
SnmpMibTable * viewTables;
|
|
SnmpTfxView * tfxView;
|
|
|
|
SnmpMibEntry * newEntry = NULL;
|
|
SnmpTableXlat * newXlat = NULL;
|
|
|
|
// initialize
|
|
*mibEntry = NULL;
|
|
*tblXlat = NULL;
|
|
|
|
// retrieve view information
|
|
tfxView = &tfxInfo->tfxViews[vlIndex];
|
|
|
|
// retrieve view object identifier
|
|
viewOid = &tfxView->mibView->viewOid;
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: TFX: FindMibEntry; comp(%s, ",
|
|
SnmpUtilOidToA(&vb->name)
|
|
));
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"%s).\n",
|
|
SnmpUtilOidToA(viewOid)
|
|
));
|
|
|
|
// if the prefix exactly matchs it is root oid
|
|
if (!SnmpUtilOidCmp(&vb->name, viewOid)) {
|
|
SNMPDBG((SNMP_LOG_VERBOSE, "SNMP: TFX: requested oid is root.\n"));
|
|
*errorStatus = SNMP_ERRORSTATUS_NOSUCHNAME;
|
|
return;
|
|
}
|
|
|
|
// if the prefix does not match it is not in hash table
|
|
if (SnmpUtilOidNCmp(&vb->name, viewOid, viewOid->idLength)) {
|
|
SNMPDBG((SNMP_LOG_TRACE, "SNMP: TFX: requested oid not in view.\n"));
|
|
*errorStatus = SNMP_ERRORSTATUS_NOSUCHNAME;
|
|
return;
|
|
}
|
|
|
|
// construct new oid sans root prefix
|
|
hashOid.ids = &vb->name.ids[viewOid->idLength];
|
|
hashOid.idLength = vb->name.idLength - viewOid->idLength;
|
|
|
|
// retrieve mib entry and index via hash table
|
|
OidToMibEntry(&hashOid, tfxView->hashTable, &newEntry);
|
|
|
|
// check if mib entry found
|
|
fFoundOk = (newEntry != NULL);
|
|
|
|
// try mib tables
|
|
if (!fFoundOk) {
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: TFX: searching mib tables for %s.\n",
|
|
SnmpUtilOidToA(&hashOid)
|
|
));
|
|
|
|
// retrieve mib table information
|
|
numTables = tfxView->mibView->viewTables.len;
|
|
viewTables = tfxView->mibView->viewTables.list;
|
|
|
|
// scan mib tables for a match to the given oid
|
|
for (i=0; (i < numTables) && !fFoundOk; i++, viewTables++) {
|
|
|
|
// retrieve entry for table entry
|
|
numItems = viewTables->numColumns;
|
|
newEntry = viewTables->tableEntry;
|
|
|
|
if (!SnmpUtilOidNCmp(
|
|
&hashOid,
|
|
&newEntry->mibOid,
|
|
newEntry->mibOid.idLength)) {
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: TFX: searching table 0x%08lx (%s).\n",
|
|
newEntry, SnmpUtilOidToA(&newEntry->mibOid)
|
|
));
|
|
|
|
// next
|
|
++newEntry;
|
|
|
|
// scan mib table entries for a match
|
|
for (j=0; j < numItems; j++, newEntry++) {
|
|
|
|
// compare with oid of table entry
|
|
if (!SnmpUtilOidNCmp(
|
|
&hashOid,
|
|
&newEntry->mibOid,
|
|
newEntry->mibOid.idLength)) {
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: TFX: validating mib entry 0x%08lx (%s).\n",
|
|
newEntry, SnmpUtilOidToA(&newEntry->mibOid)
|
|
));
|
|
|
|
// construct new oid sans table entry prefix
|
|
indexOid.ids =
|
|
&hashOid.ids[newEntry->mibOid.idLength];
|
|
indexOid.idLength =
|
|
hashOid.idLength - newEntry->mibOid.idLength;
|
|
|
|
// verify rest of oid is valid index
|
|
indexComp = ValidateInstanceIdentifier(
|
|
&indexOid,
|
|
viewTables
|
|
);
|
|
fFoundOk = (indexComp < 0 && *mibAction == MIB_ACTION_GETNEXT) ||
|
|
(indexComp == 0);
|
|
|
|
// is index?
|
|
if (fFoundOk) {
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: TFX: saving index oid %s.\n",
|
|
SnmpUtilOidToA(&indexOid)
|
|
));
|
|
|
|
// alloc a table traslation entry only if the object is accessible
|
|
if (newEntry->mibAccess != MIB_ACCESS_NONE)
|
|
{
|
|
// allocate table translation structure
|
|
newXlat = (SnmpTableXlat *)SnmpUtilMemAlloc(
|
|
sizeof(SnmpTableXlat)
|
|
);
|
|
// Prefix bug # 445169
|
|
if (newXlat != NULL)
|
|
{
|
|
// copy index object identifier
|
|
if (! SnmpUtilOidCpy(&newXlat->txOid, &indexOid))
|
|
{
|
|
// report memory allocation problem
|
|
SNMPDBG((
|
|
SNMP_LOG_ERROR,
|
|
"SNMP: TFX: SnmpUtilOidCpy at line %d failed.\n",
|
|
__LINE__));
|
|
|
|
// free previous allocated memory
|
|
SnmpUtilMemFree(newXlat);
|
|
*errorStatus = SNMP_ERRORSTATUS_GENERR;
|
|
return; // bail...
|
|
}
|
|
|
|
// save table information
|
|
newXlat->txInfo = viewTables;
|
|
newXlat->txIndex = i;
|
|
}
|
|
else
|
|
{
|
|
// report memory allocation problem
|
|
SNMPDBG((
|
|
SNMP_LOG_ERROR,
|
|
"SNMP: TFX: unable to allocate memory.\n"
|
|
));
|
|
*errorStatus = SNMP_ERRORSTATUS_GENERR;
|
|
return; // bail...
|
|
}
|
|
}
|
|
|
|
break; // finished...
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
} else {
|
|
|
|
UINT newOff;
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: TFX: searching mib tables for %s.\n",
|
|
SnmpUtilOidToA(&hashOid)
|
|
));
|
|
|
|
// retrieve mib table information
|
|
numTables = tfxView->mibView->viewTables.len;
|
|
viewTables = tfxView->mibView->viewTables.list;
|
|
|
|
// scan mib tables for an entry in table
|
|
for (i=0; i < numTables; i++, viewTables++) {
|
|
|
|
// columns are positioned after entry
|
|
if (newEntry > viewTables->tableEntry) {
|
|
|
|
// calculate the difference between pointers
|
|
newOff = (UINT)((ULONG_PTR)newEntry - (ULONG_PTR)viewTables->tableEntry);
|
|
|
|
// calculate table offset
|
|
newOff /= sizeof(SnmpMibEntry);
|
|
|
|
// determine if entry within region
|
|
if (newOff <= viewTables->numColumns &&
|
|
newEntry->mibAccess != MIB_ACCESS_NONE) {
|
|
|
|
// allocate table translation structure
|
|
newXlat = (SnmpTableXlat *)SnmpUtilMemAlloc(
|
|
sizeof(SnmpTableXlat)
|
|
);
|
|
// Prefix bug # 445169
|
|
if (newXlat != NULL)
|
|
{
|
|
// save table information
|
|
newXlat->txInfo = viewTables;
|
|
newXlat->txIndex = i;
|
|
|
|
// initialize index oid
|
|
newXlat->txOid.ids = NULL;
|
|
newXlat->txOid.idLength = 0;
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"SNMP: TFX: mib entry is in table 0x%08lx (%s).\n",
|
|
viewTables->tableEntry,
|
|
SnmpUtilOidToA(&viewTables->tableEntry->mibOid)
|
|
));
|
|
|
|
break; // finished...
|
|
}
|
|
else
|
|
{
|
|
// report memory allocation problem
|
|
SNMPDBG((
|
|
SNMP_LOG_ERROR,
|
|
"SNMP: TFX: unable to allocate memory.\n"
|
|
));
|
|
*errorStatus = SNMP_ERRORSTATUS_GENERR;
|
|
return; // bail...
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// found entry?
|
|
if (fFoundOk) {
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: TFX: FindMibEntry; found %s\n",
|
|
SnmpUtilOidToA(&newEntry->mibOid)
|
|
));
|
|
// pass back results
|
|
*mibEntry = newEntry;
|
|
*tblXlat = newXlat;
|
|
|
|
} else {
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: TFX: unable to exactly match varbind.\n"
|
|
));
|
|
|
|
// unable to locate varbind in mib table
|
|
*errorStatus = SNMP_ERRORSTATUS_NOSUCHNAME;
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
FindNextMibEntry(
|
|
SnmpTfxInfo * tfxInfo,
|
|
RFC1157VarBind * vb,
|
|
SnmpMibEntry ** mibEntry,
|
|
UINT * mibAction,
|
|
SnmpTableXlat ** tblXlat,
|
|
UINT vlIndex,
|
|
UINT * errorStatus
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Locates next mib entry associated with given varbind.
|
|
|
|
Arguments:
|
|
|
|
tfxInfo - context info.
|
|
vb - variable to locate.
|
|
mibEntry - mib entry information.
|
|
mibAction - mib action (may be updated).
|
|
tblXlat - table translation info.
|
|
vlIndex - index into view list.
|
|
errorStatus - used to indicate success or failure.
|
|
|
|
Return Values:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
UINT mibStatus;
|
|
|
|
SnmpMibEntry * newEntry = NULL;
|
|
SnmpTableXlat * newXlat = NULL;
|
|
|
|
SnmpTfxView * tfxView;
|
|
|
|
// table?
|
|
if (*tblXlat) {
|
|
SNMPDBG((SNMP_LOG_VERBOSE, "SNMP: TFX: querying table.\n"));
|
|
return; // simply query table...
|
|
}
|
|
|
|
// retrieve view information
|
|
tfxView = &tfxInfo->tfxViews[vlIndex];
|
|
|
|
// retrieve entry
|
|
newEntry = *mibEntry;
|
|
|
|
// initialize
|
|
*mibEntry = NULL;
|
|
*tblXlat = NULL;
|
|
|
|
// continuing?
|
|
if (newEntry) {
|
|
// next
|
|
++newEntry;
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"SNMP: TFX: searching mib at next entry 0x%08lx (%s).\n",
|
|
newEntry,
|
|
SnmpUtilOidToA(&newEntry->mibOid)
|
|
));
|
|
} else {
|
|
// retrieve first mib entry in supported view
|
|
newEntry = tfxView->mibView->viewScalars.list;
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"SNMP: TFX: searching mib at first entry 0x%08lx.\n",
|
|
newEntry
|
|
));
|
|
}
|
|
|
|
// initialize status to start search
|
|
mibStatus = SNMP_ERRORSTATUS_NOSUCHNAME;
|
|
|
|
// scan
|
|
for (;; newEntry++) {
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: TFX: FindNextMibEntry; scanning view %s ",
|
|
SnmpUtilOidToA(&tfxView->mibView->viewOid)
|
|
));
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
" scalar %s.\n",
|
|
SnmpUtilOidToA(&newEntry->mibOid)
|
|
));
|
|
|
|
// if last entry then we stop looking
|
|
if (newEntry->mibType == ASN_PRIVATE_EOM) {
|
|
|
|
SNMPDBG((SNMP_LOG_TRACE, "SNMP: TFX: encountered end of mib.\n"));
|
|
|
|
*errorStatus = SNMP_ERRORSTATUS_NOSUCHNAME;
|
|
return; // bail...
|
|
}
|
|
|
|
// skip over place holder mib entries
|
|
if (newEntry->mibType != ASN_PRIVATE_NODE) {
|
|
|
|
// validate asn value against info in mib entry
|
|
ValidateAsnAny(&vb->value, newEntry, *mibAction, &mibStatus);
|
|
|
|
// bail if we found a valid entry...
|
|
if (mibStatus == SNMP_ERRORSTATUS_NOERROR) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// retrieved an entry but is it in a table?
|
|
if (mibStatus == SNMP_ERRORSTATUS_NOERROR) {
|
|
|
|
UINT i;
|
|
UINT newOff;
|
|
UINT numTables;
|
|
|
|
SnmpMibTable * viewTables;
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"SNMP: TFX: mib entry 0x%08lx found (%s).\n",
|
|
newEntry, SnmpUtilOidToA(&newEntry->mibOid)
|
|
));
|
|
|
|
// retrieve table information from view
|
|
numTables = tfxView->mibView->viewTables.len;
|
|
viewTables = tfxView->mibView->viewTables.list;
|
|
|
|
// scan mib tables for an entry in table
|
|
for (i=0; i < numTables; i++, viewTables++) {
|
|
|
|
// columns are positioned after entry
|
|
if (newEntry > viewTables->tableEntry) {
|
|
|
|
// calculate the difference between pointers
|
|
newOff = (UINT)((ULONG_PTR)newEntry - (ULONG_PTR)viewTables->tableEntry);
|
|
|
|
// calculate table offset
|
|
newOff /= sizeof(SnmpMibEntry);
|
|
|
|
// determine if entry within region
|
|
if (newOff <= viewTables->numColumns) {
|
|
|
|
// allocate table translation structure
|
|
newXlat = (SnmpTableXlat *)SnmpUtilMemAlloc(
|
|
sizeof(SnmpTableXlat)
|
|
);
|
|
|
|
// Prefix bug # 445169
|
|
if (newXlat != NULL)
|
|
{
|
|
// save table information
|
|
newXlat->txInfo = viewTables;
|
|
newXlat->txIndex = i;
|
|
|
|
// initialize index oid
|
|
newXlat->txOid.ids = NULL;
|
|
newXlat->txOid.idLength = 0;
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"SNMP: TFX: mib entry is in table 0x%08lx (%s).\n",
|
|
viewTables->tableEntry,
|
|
SnmpUtilOidToA(&viewTables->tableEntry->mibOid)
|
|
));
|
|
|
|
break; // finished...
|
|
}
|
|
else
|
|
{
|
|
// report memory allocation problem
|
|
SNMPDBG((
|
|
SNMP_LOG_ERROR,
|
|
"SNMP: TFX: unable to allocate memory.\n"
|
|
));
|
|
|
|
*errorStatus = SNMP_ERRORSTATUS_GENERR;
|
|
return; // bail...
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// pass back results
|
|
*mibEntry = newEntry;
|
|
*tblXlat = newXlat;
|
|
|
|
// update mib action of scalar getnext
|
|
if (!newXlat && (*mibAction == MIB_ACTION_GETNEXT)) {
|
|
|
|
*mibAction = MIB_ACTION_GET;
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"SNMP: TFX: altered mib action to MIB_ACTION_GET.\n"
|
|
));
|
|
}
|
|
}
|
|
|
|
// pass back status
|
|
*errorStatus = mibStatus;
|
|
}
|
|
|
|
|
|
VOID
|
|
FindAnyMibEntry(
|
|
SnmpTfxInfo * tfxInfo,
|
|
RFC1157VarBind * vb,
|
|
SnmpMibEntry ** mibEntry,
|
|
UINT * mibAction,
|
|
SnmpTableXlat ** tblXlat,
|
|
UINT vlIndex,
|
|
UINT * errorStatus
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Locates any mib entry associated with given varbind.
|
|
|
|
Arguments:
|
|
|
|
tfxInfo - context info.
|
|
vb - variable to locate.
|
|
mibEntry - mib entry information.
|
|
mibAction - mib action (may be updated).
|
|
tblXlat - table translation info.
|
|
vlIndex - index into view list.
|
|
errorStatus - used to indicate success or failure.
|
|
|
|
Return Values:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
BOOL fExact;
|
|
BOOL fBefore;
|
|
|
|
SnmpTfxView * tfxView;
|
|
|
|
// retrieve view information
|
|
tfxView = &tfxInfo->tfxViews[vlIndex];
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: TFX: FindAnyMibEntry; comp(%s, ",
|
|
SnmpUtilOidToA(&vb->name)
|
|
));
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"%s[, %d]).\n",
|
|
SnmpUtilOidToA(&tfxView->mibView->viewOid),
|
|
tfxView->mibView->viewOid.idLength
|
|
));
|
|
|
|
// look for oid before view
|
|
fBefore = (0 > SnmpUtilOidNCmp(
|
|
&vb->name,
|
|
&tfxView->mibView->viewOid,
|
|
tfxView->mibView->viewOid.idLength
|
|
));
|
|
|
|
// look for exact match
|
|
fExact = !fBefore && !SnmpUtilOidCmp(
|
|
&vb->name,
|
|
&tfxView->mibView->viewOid
|
|
);
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: TFX: fBefore=%d fExact=%d\n",
|
|
fBefore,
|
|
fExact
|
|
));
|
|
// check for random oid...
|
|
if (!fBefore && !fExact) {
|
|
|
|
AsnObjectIdentifier relOid;
|
|
AsnObjectIdentifier * viewOid;
|
|
SnmpMibEntry * newEntry = NULL;
|
|
|
|
// point to the first item in the list
|
|
newEntry = tfxView->mibView->viewScalars.list;
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"SNMP: TFX: linear search from first entry 0x%08lx.\n",
|
|
newEntry
|
|
));
|
|
|
|
// retrieve the view object identifier
|
|
viewOid = &tfxView->mibView->viewOid;
|
|
|
|
// construct new oid sans root prefix
|
|
relOid.ids = &vb->name.ids[viewOid->idLength];
|
|
relOid.idLength = vb->name.idLength - viewOid->idLength;
|
|
|
|
// scan mib entries
|
|
while ((newEntry->mibType != ASN_PRIVATE_EOM) &&
|
|
(SnmpUtilOidCmp(&relOid, &newEntry->mibOid) > 0)) {
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: TFX: skipping %s.\n",
|
|
SnmpUtilOidToA(&newEntry->mibOid)
|
|
));
|
|
|
|
// next
|
|
newEntry++;
|
|
}
|
|
|
|
// if last entry then we stop looking
|
|
if (newEntry->mibType == ASN_PRIVATE_EOM) {
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"SNMP: TFX: encountered end of mib.\n"
|
|
));
|
|
|
|
*errorStatus = SNMP_ERRORSTATUS_NOSUCHNAME;
|
|
return; // bail...
|
|
}
|
|
|
|
// backup to find next
|
|
*mibEntry = --newEntry;
|
|
*tblXlat = NULL;
|
|
|
|
// find next
|
|
FindNextMibEntry(
|
|
tfxInfo,
|
|
vb,
|
|
mibEntry,
|
|
mibAction,
|
|
tblXlat,
|
|
vlIndex,
|
|
errorStatus
|
|
);
|
|
|
|
} else {
|
|
|
|
// initialize
|
|
*mibEntry = NULL;
|
|
*tblXlat = NULL;
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"SNMP: TFX: searching for first entry.\n"
|
|
));
|
|
|
|
// find next
|
|
FindNextMibEntry(
|
|
tfxInfo,
|
|
vb,
|
|
mibEntry,
|
|
mibAction,
|
|
tblXlat,
|
|
vlIndex,
|
|
errorStatus
|
|
);
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: TFX: FindAnyMibEntry; error %d on %s(.",
|
|
*errorStatus,
|
|
SnmpUtilOidToA(&tfxInfo->tfxViews[vlIndex].mibView->viewOid)
|
|
));
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"%s).\n",
|
|
SnmpUtilOidToA(&(*mibEntry)->mibOid)
|
|
));
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
VarBindToMibEntry(
|
|
SnmpTfxInfo * tfxInfo,
|
|
RFC1157VarBind * vb,
|
|
SnmpMibEntry ** mibEntry,
|
|
UINT * mibAction,
|
|
SnmpTableXlat ** tblXlat,
|
|
UINT vlIndex,
|
|
UINT * errorStatus
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Locates mib entry associated with given varbind.
|
|
|
|
Arguments:
|
|
|
|
tfxInfo - context information.
|
|
vb - variable to locate.
|
|
mibEntry - mib entry information.
|
|
mibAction - mib action (may be updated).
|
|
tblXlat - table translation info.
|
|
vlIndex - index into view list.
|
|
errorStatus - used to indicate success or failure.
|
|
|
|
Return Values:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
BOOL fAnyOk;
|
|
BOOL fFoundOk;
|
|
BOOL fErrorOk;
|
|
|
|
// determine whether we need exact match
|
|
fAnyOk = (*mibAction == MIB_ACTION_GETNEXT);
|
|
|
|
// find match
|
|
FindMibEntry(
|
|
tfxInfo,
|
|
vb,
|
|
mibEntry,
|
|
mibAction,
|
|
tblXlat,
|
|
vlIndex,
|
|
errorStatus
|
|
);
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: TFX: VarBindToMibEntry; errorStatus=%d.\n",
|
|
*errorStatus
|
|
));
|
|
|
|
// get next?
|
|
if (fAnyOk) {
|
|
|
|
// search again
|
|
if (*errorStatus == SNMP_ERRORSTATUS_NOERROR) {
|
|
|
|
// find next entry
|
|
FindNextMibEntry(
|
|
tfxInfo,
|
|
vb,
|
|
mibEntry,
|
|
mibAction,
|
|
tblXlat,
|
|
vlIndex,
|
|
errorStatus
|
|
);
|
|
|
|
} else if (*errorStatus == SNMP_ERRORSTATUS_NOSUCHNAME) {
|
|
|
|
// find any entry
|
|
FindAnyMibEntry(
|
|
tfxInfo,
|
|
vb,
|
|
mibEntry,
|
|
mibAction,
|
|
tblXlat,
|
|
vlIndex,
|
|
errorStatus
|
|
);
|
|
}
|
|
|
|
} else if (*errorStatus == SNMP_ERRORSTATUS_NOERROR) {
|
|
|
|
// validate asn value against mib entry information
|
|
ValidateAsnAny(&vb->value, *mibEntry, *mibAction, errorStatus);
|
|
|
|
// make sure valid before passing back entry
|
|
if (*errorStatus != SNMP_ERRORSTATUS_NOERROR) {
|
|
|
|
// table entry?
|
|
if (*tblXlat) {
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: TFX: freeing index info (%s).\n",
|
|
SnmpUtilOidToA(&(*tblXlat)->txOid)
|
|
));
|
|
|
|
// free index oid
|
|
SnmpUtilOidFree(&(*tblXlat)->txOid);
|
|
|
|
// free table info
|
|
SnmpUtilMemFree(*tblXlat);
|
|
|
|
}
|
|
|
|
// nullify results
|
|
*mibEntry = NULL;
|
|
*tblXlat = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
BOOL
|
|
CheckUpdateIndex(
|
|
AsnObjectIdentifier *indexOid,
|
|
UINT nStartFrom,
|
|
UINT nExpecting
|
|
)
|
|
/*++
|
|
Routine Description:
|
|
|
|
Checks if an index OID contains all the components expected.
|
|
If not, the index is updated to point before the very first
|
|
OID requested.
|
|
|
|
Arguments:
|
|
|
|
indexOid - pointer to the index to be checked.
|
|
nStartFrom - the point from where the index is checked.
|
|
nExpecting - the index should have at least expectTo components from startFrom.
|
|
|
|
Return value:
|
|
TRUE if index was valid or has been updated successfully.
|
|
FALSE otherwise (index was shorter then expected and all filled with 0s).
|
|
|
|
--*/
|
|
{
|
|
int i;
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: TFX: CheckUpdateIndex; checking %s.\n",
|
|
SnmpUtilOidToA(indexOid)
|
|
));
|
|
|
|
if (indexOid->idLength >= nStartFrom + nExpecting)
|
|
{
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: TFX: CheckUpdateIndex; valid, unchanged.\n"
|
|
));
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
for (i = indexOid->idLength-1; i >= (int)nStartFrom; i--)
|
|
{
|
|
if (indexOid->ids[i] > 0)
|
|
{
|
|
indexOid->ids[i]--;
|
|
indexOid->idLength = i+1;
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: TFX: CheckUpdateIndex; valid, changed to %s.\n",
|
|
SnmpUtilOidToA(indexOid)
|
|
));
|
|
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: TFX: CheckUpdateIndex; invalid, to be removed.\n"
|
|
));
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
VOID
|
|
ParseInstanceIdentifier(
|
|
SnmpTableXlat * tblXlat,
|
|
AsnAny * objArray,
|
|
UINT mibAction,
|
|
UINT * errorStatus
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Converts table index oid into object array.
|
|
|
|
Arguments:
|
|
|
|
tblXlat - table translation information.
|
|
objArray - instrumentation object array.
|
|
mibAction - action requested of subagent.
|
|
|
|
Return Values:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
UINT i;
|
|
UINT j;
|
|
UINT k;
|
|
UINT l;
|
|
UINT m;
|
|
|
|
BOOL fFixed;
|
|
BOOL fLimit;
|
|
BOOL fIndex;
|
|
BOOL fEmpty;
|
|
BOOL fExceed;
|
|
|
|
UINT numItems;
|
|
|
|
SnmpMibEntry * mibEntry;
|
|
AsnObjectIdentifier * indexOid;
|
|
|
|
LPDWORD lpIpAddress;
|
|
|
|
*errorStatus = SNMP_ERRORSTATUS_NOERROR; // init return status
|
|
|
|
// retrieve index oid
|
|
indexOid = &tblXlat->txOid;
|
|
|
|
// is this valid oid
|
|
fEmpty = (indexOid->idLength == 0);
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"SNMP: TFX: converting index %s to obj array via table 0x%08lx.\n",
|
|
fEmpty ? "<tbd>" : SnmpUtilOidToA(indexOid), tblXlat->txInfo
|
|
));
|
|
|
|
// retrieve root entry and entry count
|
|
numItems = tblXlat->txInfo->numIndices;
|
|
|
|
// see if the table indices are specified
|
|
fIndex = (tblXlat->txInfo->tableIndices != NULL);
|
|
fExceed = FALSE;
|
|
// scan mib entries of table indices
|
|
for (i=0, j=0; (i < numItems) && (j < indexOid->idLength); i++) {
|
|
|
|
// get mib entry from table or directly
|
|
mibEntry = fIndex ? tblXlat->txInfo->tableIndices[i]
|
|
: &tblXlat->txInfo->tableEntry[i+1]
|
|
;
|
|
|
|
// retrieve array index
|
|
k = (mibAction == MIB_ACTION_SET)
|
|
? (UINT)(CHAR)mibEntry->mibSetBufOff
|
|
: (UINT)(CHAR)mibEntry->mibGetBufOff
|
|
;
|
|
|
|
// determine type
|
|
switch (mibEntry->mibType) {
|
|
|
|
// variable length types
|
|
case ASN_OBJECTIDENTIFIER:
|
|
|
|
// check whether this is a fixed length variable or not
|
|
fLimit = (mibEntry->mibMinimum || mibEntry->mibMaximum);
|
|
fFixed = (fLimit && (mibEntry->mibMinimum == mibEntry->mibMaximum));
|
|
|
|
// validate
|
|
if (fFixed) {
|
|
|
|
// fixed length; indexOid should have at least l components more
|
|
l = mibEntry->mibMaximum;
|
|
|
|
if (!CheckUpdateIndex(indexOid, j, l))
|
|
{
|
|
// out from switch and for
|
|
j+=l;
|
|
break;
|
|
}
|
|
|
|
} else {
|
|
// variable length
|
|
l = indexOid->ids[j];
|
|
|
|
if (!CheckUpdateIndex(indexOid, j, l+1))
|
|
{
|
|
// out from switch and for
|
|
j+=l+1;
|
|
break;
|
|
}
|
|
|
|
// BUG# 457746
|
|
// the length of OID might have been changed by
|
|
// CheckUpdateIndex
|
|
l = indexOid->ids[j]; // update the length if necessary
|
|
|
|
j++;
|
|
}
|
|
|
|
// copy the type of asn variable
|
|
objArray[k].asnType = mibEntry->mibType;
|
|
|
|
// allocate object using length above
|
|
objArray[k].asnValue.object.idLength = l;
|
|
objArray[k].asnValue.object.ids = SnmpUtilMemAlloc(
|
|
objArray[k].asnValue.object.idLength * sizeof(UINT)
|
|
);
|
|
|
|
if (objArray[k].asnValue.object.ids == NULL)
|
|
{
|
|
// report memory allocation problem
|
|
SNMPDBG((
|
|
SNMP_LOG_ERROR,
|
|
"SNMP: TFX: unable to allocate memory.\n"
|
|
));
|
|
objArray[k].asnValue.object.idLength = 0;
|
|
*errorStatus = SNMP_ERRORSTATUS_GENERR;
|
|
return; // bail...
|
|
}
|
|
// transfer data
|
|
for (m=0; m < l; m++, j++) {
|
|
|
|
// transfer oid element to buffer
|
|
if (!fExceed && j < indexOid->idLength)
|
|
{
|
|
objArray[k].asnValue.object.ids[m] = indexOid->ids[j];
|
|
}
|
|
else
|
|
{
|
|
if (!fExceed)
|
|
fExceed = TRUE;
|
|
// this certainly is the last index from the request
|
|
}
|
|
|
|
if (fExceed)
|
|
{
|
|
objArray[k].asnValue.object.ids[m] = (UINT)(-1);
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
case ASN_RFC1155_OPAQUE:
|
|
case ASN_OCTETSTRING:
|
|
|
|
// check whether this is a fixed length variable or not
|
|
fLimit = (mibEntry->mibMinimum || mibEntry->mibMaximum);
|
|
fFixed = (fLimit && (mibEntry->mibMinimum == mibEntry->mibMaximum));
|
|
|
|
// validate
|
|
if (fFixed) {
|
|
|
|
// fixed length
|
|
l = mibEntry->mibMaximum;
|
|
|
|
if (!CheckUpdateIndex(indexOid, j, l))
|
|
{
|
|
// out from switch and for
|
|
j+=l;
|
|
break;
|
|
}
|
|
|
|
} else {
|
|
|
|
// variable length
|
|
l = indexOid->ids[j];
|
|
|
|
if (!CheckUpdateIndex(indexOid, j, l+1))
|
|
{
|
|
j+=l+1;
|
|
break;
|
|
}
|
|
|
|
// BUG# 457746
|
|
// the length of octet string might have been changed by
|
|
// CheckUpdateIndex
|
|
l = indexOid->ids[j]; // update the length if necessary
|
|
|
|
j++;
|
|
}
|
|
|
|
// copy the type of asn variable
|
|
objArray[k].asnType = mibEntry->mibType;
|
|
|
|
// allocate object
|
|
objArray[k].asnValue.string.length = l;
|
|
objArray[k].asnValue.string.dynamic = TRUE;
|
|
objArray[k].asnValue.string.stream = SnmpUtilMemAlloc(
|
|
objArray[k].asnValue.string.length * sizeof(CHAR)
|
|
);
|
|
|
|
if (objArray[k].asnValue.string.stream == NULL)
|
|
{
|
|
// report memory allocation problem
|
|
SNMPDBG((
|
|
SNMP_LOG_ERROR,
|
|
"SNMP: TFX: unable to allocate memory.\n"
|
|
));
|
|
objArray[k].asnValue.string.length = 0;
|
|
objArray[k].asnValue.string.dynamic = FALSE;
|
|
*errorStatus = SNMP_ERRORSTATUS_GENERR;
|
|
return; // bail...
|
|
}
|
|
// transfer data
|
|
for (m=0; m < l; m++, j++) {
|
|
|
|
// convert oid element to character
|
|
if (j < indexOid->idLength)
|
|
{
|
|
if (!fExceed && indexOid->ids[j] <= (UCHAR)(-1))
|
|
objArray[k].asnValue.string.stream[m] = (BYTE)(indexOid->ids[j]);
|
|
else
|
|
fExceed=TRUE;
|
|
}
|
|
else
|
|
{
|
|
if (!fExceed)
|
|
fExceed = TRUE;
|
|
// this certainly is the last index from the request
|
|
}
|
|
|
|
if (fExceed)
|
|
{
|
|
objArray[k].asnValue.string.stream[m] = (UCHAR)(-1);
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
// implicit fixed size
|
|
case ASN_RFC1155_IPADDRESS:
|
|
|
|
if (!CheckUpdateIndex(indexOid, j, 4))
|
|
{
|
|
// out from switch and for
|
|
j+=4;
|
|
break;
|
|
}
|
|
|
|
// copy the type of asn variable
|
|
objArray[k].asnType = mibEntry->mibType;
|
|
|
|
// allocate object
|
|
objArray[k].asnValue.string.length = 4;
|
|
objArray[k].asnValue.string.dynamic = TRUE;
|
|
objArray[k].asnValue.string.stream = SnmpUtilMemAlloc(
|
|
objArray[k].asnValue.string.length * sizeof(CHAR)
|
|
);
|
|
|
|
|
|
if (objArray[k].asnValue.string.stream == NULL)
|
|
{
|
|
// report memory allocation problem
|
|
SNMPDBG((
|
|
SNMP_LOG_ERROR,
|
|
"SNMP: TFX: unable to allocate memory.\n"
|
|
));
|
|
objArray[k].asnValue.string.length = 0;
|
|
objArray[k].asnValue.string.dynamic = FALSE;
|
|
*errorStatus = SNMP_ERRORSTATUS_GENERR;
|
|
return; // bail...
|
|
}
|
|
|
|
// cast to dword in order to manipulate ip address
|
|
lpIpAddress = (LPDWORD)objArray[k].asnValue.string.stream;
|
|
|
|
|
|
// transfer data into buffer
|
|
for (m=0; m<4; m++, j++)
|
|
{
|
|
*lpIpAddress <<= 8;
|
|
|
|
if (!fExceed && j < indexOid->idLength)
|
|
{
|
|
if (indexOid->ids[j] <= (UCHAR)(-1))
|
|
*lpIpAddress += indexOid->ids[j];
|
|
else
|
|
fExceed = TRUE;
|
|
}
|
|
else
|
|
{
|
|
if (!fExceed)
|
|
fExceed = TRUE;
|
|
// this certainly is the last index from the request
|
|
}
|
|
if (fExceed)
|
|
{
|
|
*lpIpAddress += (UCHAR)(-1);
|
|
}
|
|
}
|
|
|
|
// ensure network byte order
|
|
*lpIpAddress = htonl(*lpIpAddress);
|
|
|
|
break;
|
|
|
|
case ASN_RFC1155_COUNTER:
|
|
case ASN_RFC1155_GAUGE:
|
|
case ASN_RFC1155_TIMETICKS:
|
|
case ASN_INTEGER:
|
|
|
|
// copy the type of asn variable
|
|
objArray[k].asnType = mibEntry->mibType;
|
|
|
|
// transfer value as integer
|
|
objArray[k].asnValue.number = fExceed ? (UINT)(-1) : indexOid->ids[j];
|
|
j++;
|
|
break;
|
|
|
|
default:
|
|
// invalidate
|
|
j = INVALID_INDEX;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
IsTableIndex(
|
|
SnmpMibEntry * mibEntry,
|
|
SnmpTableXlat * tblXlat
|
|
)
|
|
{
|
|
UINT newOff;
|
|
BOOL fFoundOk = FALSE;
|
|
BOOL fIndex;
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: TFX: comparing mibEntry 0x%08lx to table 0x%08lx.\n",
|
|
mibEntry,
|
|
tblXlat->txInfo
|
|
));
|
|
|
|
// see if the table indices are specified
|
|
fIndex = (tblXlat->txInfo->tableIndices != NULL);
|
|
|
|
#if DBG
|
|
newOff = 0;
|
|
#endif
|
|
|
|
if (fIndex) {
|
|
|
|
// rummage through index list looking for match
|
|
for (newOff = 0; (newOff < tblXlat->txInfo->numIndices) && !fFoundOk; newOff++ ) {
|
|
|
|
// compare mib entry with the next specified index
|
|
fFoundOk = (mibEntry == tblXlat->txInfo->tableIndices[newOff]);
|
|
}
|
|
|
|
} else {
|
|
|
|
// make sure pointer greater than table entry
|
|
if (mibEntry > tblXlat->txInfo->tableEntry) {
|
|
|
|
// calculate the difference between pointers
|
|
newOff = (UINT)((ULONG_PTR)mibEntry - (ULONG_PTR)tblXlat->txInfo->tableEntry);
|
|
|
|
// calculate table offset
|
|
newOff /= sizeof(SnmpMibEntry);
|
|
|
|
// determine whether entry within region
|
|
fFoundOk = (newOff <= tblXlat->txInfo->numIndices);
|
|
}
|
|
}
|
|
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: TFX: mibEntry %s a component of the table's index (off=%d, len=%d).\n",
|
|
fFoundOk ? "is" : "is not",
|
|
newOff,
|
|
tblXlat->txInfo->numIndices
|
|
));
|
|
|
|
return fFoundOk;
|
|
}
|
|
|
|
|
|
VOID
|
|
MibEntryToQueryList(
|
|
SnmpMibEntry * mibEntry,
|
|
UINT mibAction,
|
|
SnmpExtQueryList * ql,
|
|
SnmpTableXlat * tblXlat,
|
|
UINT vlIndex,
|
|
RFC1157VarBindList * vbl,
|
|
UINT vb,
|
|
UINT * errorStatus
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Converts mib entry information into subagent query.
|
|
|
|
Arguments:
|
|
|
|
mibEntry - mib information.
|
|
mibAction - action to perform.
|
|
ql - list of subagent queries.
|
|
tableXlat - table translation info.
|
|
vlIndex - index into view list.
|
|
vbl - original varbind list.
|
|
vb - original varbind.
|
|
errorStatus - used to indicate success or failure.
|
|
|
|
Return Values:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
UINT i;
|
|
UINT j;
|
|
UINT viewType;
|
|
|
|
FARPROC extFunc;
|
|
|
|
AsnAny * objArray;
|
|
SnmpExtQuery * extQuery;
|
|
|
|
SnmpExtQuery * tmpExtQuery = NULL; // prefix Bug 445172
|
|
SnmpVarBindXlat * tmpVblXlat = NULL; // prefix Bug 445172
|
|
|
|
|
|
BOOL fFoundOk = FALSE;
|
|
|
|
// determine instrumentation callback
|
|
extFunc = (mibAction == MIB_ACTION_SET)
|
|
? (FARPROC)mibEntry->mibSetFunc
|
|
: (FARPROC)mibEntry->mibGetFunc
|
|
;
|
|
|
|
// process existing queries
|
|
for (i=0; (i < ql->len) && !fFoundOk; i++) {
|
|
|
|
// retrieve query ptr
|
|
extQuery = &ql->query[i];
|
|
|
|
// determine if a similar query exists
|
|
fFoundOk = ((extQuery->extFunc == extFunc) &&
|
|
(extQuery->mibAction == mibAction));
|
|
|
|
// compare table indices (if any)
|
|
if (fFoundOk && extQuery->tblXlat) {
|
|
|
|
// make sure
|
|
if (tblXlat) {
|
|
|
|
// compare index oids...
|
|
fFoundOk = !SnmpUtilOidCmp(
|
|
&extQuery->tblXlat->txOid,
|
|
&tblXlat->txOid
|
|
);
|
|
|
|
} else {
|
|
|
|
// hmmm...
|
|
fFoundOk = FALSE;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
// append entry
|
|
if (!fFoundOk) {
|
|
|
|
ql->len++; // add new query to end of list
|
|
tmpExtQuery = (SnmpExtQuery *)SnmpUtilMemReAlloc(
|
|
ql->query,
|
|
ql->len * sizeof(SnmpExtQuery)
|
|
);
|
|
// Prefix bug 445172
|
|
// check memory re-allocation
|
|
if (tmpExtQuery == NULL)
|
|
{
|
|
if (tblXlat)
|
|
{
|
|
// free table oid
|
|
SnmpUtilOidFree(&tblXlat->txOid);
|
|
|
|
// free table info
|
|
SnmpUtilMemFree(tblXlat);
|
|
}
|
|
ql->len--; // rollback
|
|
// report memory allocation problem
|
|
*errorStatus = SNMP_ERRORSTATUS_GENERR;
|
|
return; // bail...
|
|
}
|
|
ql->query = tmpExtQuery;
|
|
|
|
// retrieve new query pointer
|
|
extQuery = &ql->query[ql->len-1];
|
|
|
|
// save common information
|
|
extQuery->mibAction = mibAction;
|
|
extQuery->viewType = MIB_VIEW_NORMAL;
|
|
extQuery->extFunc = extFunc;
|
|
|
|
// initialize list
|
|
extQuery->vblNum = 0;
|
|
extQuery->vblXlat = NULL;
|
|
extQuery->tblXlat = NULL;
|
|
|
|
// size the instrumentation buffer
|
|
extQuery->extData.len = (mibAction == MIB_ACTION_SET)
|
|
? mibEntry->mibSetBufLen
|
|
: mibEntry->mibGetBufLen
|
|
;
|
|
|
|
// allocate the instrumentation buffer
|
|
extQuery->extData.data = SnmpUtilMemAlloc(
|
|
extQuery->extData.len
|
|
);
|
|
|
|
// check memory allocation
|
|
if (extQuery->extData.data) {
|
|
|
|
// table?
|
|
if (tblXlat) {
|
|
|
|
// retrieve object array pointer
|
|
objArray = (AsnAny *)(extQuery->extData.data);
|
|
|
|
// Prefix 118006
|
|
// initialize asn array
|
|
ParseInstanceIdentifier(tblXlat, objArray, mibAction, errorStatus);
|
|
if (*errorStatus != SNMP_ERRORSTATUS_NOERROR)
|
|
{
|
|
// logging...
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"SNMP: TFX: unable to ParseInstanceIdentifier with table info 0x%08lx.\n",
|
|
tblXlat
|
|
));
|
|
SnmpUtilMemFree(extQuery->extData.data);
|
|
extQuery->extData.data = NULL; // null pointer to avoid double free or deref.
|
|
extQuery->extData.len = 0;
|
|
|
|
// free table oid
|
|
SnmpUtilOidFree(&tblXlat->txOid);
|
|
// free table info
|
|
SnmpUtilMemFree(tblXlat);
|
|
|
|
|
|
ql->len--; // rollback
|
|
|
|
return; // bail
|
|
}
|
|
|
|
// save table info
|
|
extQuery->tblXlat = tblXlat;
|
|
}
|
|
|
|
} else {
|
|
|
|
// rollback
|
|
extQuery->extData.len = 0;
|
|
ql->len--;
|
|
|
|
if (tblXlat)
|
|
{
|
|
// free table oid
|
|
SnmpUtilOidFree(&tblXlat->txOid);
|
|
|
|
// free table info
|
|
SnmpUtilMemFree(tblXlat);
|
|
}
|
|
|
|
// report memory allocation problem
|
|
*errorStatus = SNMP_ERRORSTATUS_GENERR;
|
|
return; // bail...
|
|
}
|
|
|
|
} else if (tblXlat != NULL) {
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"SNMP: TFX: releasing duplicate table info 0x%08lx.\n",
|
|
tblXlat
|
|
));
|
|
|
|
// free table oid
|
|
SnmpUtilOidFree(&tblXlat->txOid);
|
|
|
|
// free table info
|
|
SnmpUtilMemFree(tblXlat);
|
|
}
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"SNMP: TFX: %s query 0x%08lx.\n",
|
|
fFoundOk ? "editing" : "adding",
|
|
extQuery
|
|
));
|
|
|
|
// copy to index
|
|
i = extQuery->vblNum;
|
|
|
|
// allocate entry
|
|
extQuery->vblNum++;
|
|
|
|
tmpVblXlat = (SnmpVarBindXlat *)SnmpUtilMemReAlloc(
|
|
extQuery->vblXlat,
|
|
extQuery->vblNum * sizeof(SnmpVarBindXlat)
|
|
);
|
|
if (tmpVblXlat == NULL)
|
|
{
|
|
// report memory allocation problem
|
|
*errorStatus = SNMP_ERRORSTATUS_GENERR;
|
|
extQuery->vblNum--; // rollback
|
|
return; // bail...
|
|
}
|
|
extQuery->vblXlat = tmpVblXlat;
|
|
|
|
|
|
// copy common xlate information
|
|
extQuery->vblXlat[i].vblIndex = vb;
|
|
extQuery->vblXlat[i].vlIndex = vlIndex;
|
|
extQuery->vblXlat[i].extQuery = NULL;
|
|
|
|
// save translation info
|
|
extQuery->vblXlat[i].mibEntry = mibEntry;
|
|
|
|
// determine offset used
|
|
i = (mibAction == MIB_ACTION_SET)
|
|
? (UINT)(CHAR)mibEntry->mibSetBufOff
|
|
: (UINT)(CHAR)mibEntry->mibGetBufOff
|
|
;
|
|
|
|
// retrieve object array pointer
|
|
objArray = (AsnAny *)(extQuery->extData.data);
|
|
|
|
// fill in only asn type if get
|
|
if (mibAction != MIB_ACTION_SET) {
|
|
|
|
// ignore table indices
|
|
if (extQuery->tblXlat &&
|
|
IsTableIndex(mibEntry,extQuery->tblXlat)) {
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: TFX: requesting index value.\n"
|
|
));
|
|
|
|
} else {
|
|
|
|
// initialize asn type to match entry
|
|
objArray[i].asnType = mibEntry->mibType;
|
|
}
|
|
|
|
} else {
|
|
|
|
// copy user-supplied value into buffer
|
|
if (! SnmpUtilAsnAnyCpy(&objArray[i], &vbl->list[vb].value) )
|
|
{
|
|
SNMPDBG((
|
|
SNMP_LOG_ERROR,
|
|
"SNMP: TFX: MibEntryToQueryList; SnmpUtilAsnAnyCpy failed.\n"
|
|
));
|
|
|
|
// report memory allocation problem
|
|
*errorStatus = SNMP_ERRORSTATUS_GENERR;
|
|
extQuery->vblNum--; // invalidate this SnmpVarBindXlat
|
|
return; // bail...
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
VarBindToQueryList(
|
|
SnmpTfxInfo * tfxInfo,
|
|
RFC1157VarBindList * vbl,
|
|
SnmpExtQueryList * ql,
|
|
UINT vb,
|
|
UINT * errorStatus,
|
|
UINT * errorIndex,
|
|
UINT queryView
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Adds varbind to query list.
|
|
|
|
Arguments:
|
|
|
|
tfxInfo - context info.
|
|
vbl - list of varbinds.
|
|
ql - list of subagent queries.
|
|
vb - index of varbind to add to query.
|
|
errorStatus - used to indicate success or failure.
|
|
errorIndex - used to identify an errant varbind.
|
|
queryView - view of query requested.
|
|
|
|
Return Values:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
INT i;
|
|
INT nDiff;
|
|
INT lastViewIndex;
|
|
|
|
BOOL fAnyOk;
|
|
BOOL fFoundOk = FALSE;
|
|
|
|
UINT mibAction;
|
|
|
|
SnmpMibView * mibView;
|
|
SnmpMibEntry * mibEntry = NULL;
|
|
SnmpTableXlat * tblXlat = NULL;
|
|
|
|
// copy request type
|
|
mibAction = ql->action;
|
|
|
|
// determine whether we need exact match
|
|
fAnyOk = (mibAction == MIB_ACTION_GETNEXT);
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: TFX: searching subagents to resolve %s (%s).\n",
|
|
SnmpUtilOidToA(&vbl->list[vb].name),
|
|
fAnyOk ? "AnyOk" : "AnyNOk"
|
|
));
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: TFX: VarBindToQueryList; scanning views from %d to %d.\n",
|
|
queryView,
|
|
(INT)tfxInfo->numViews
|
|
));
|
|
|
|
// init to NonView
|
|
lastViewIndex = -1;
|
|
|
|
// locate appropriate view (starting at queryView)
|
|
for (i = queryView; (i < (INT)tfxInfo->numViews) && !fFoundOk; i++) {
|
|
|
|
// retrieve the mib view information
|
|
mibView = tfxInfo->tfxViews[i].mibView;
|
|
|
|
// compare root oids
|
|
nDiff = SnmpUtilOidNCmp(
|
|
&vbl->list[vb].name,
|
|
&mibView->viewOid,
|
|
mibView->viewOid.idLength
|
|
);
|
|
|
|
// analyze results based on request type
|
|
fFoundOk = (!nDiff || (fAnyOk && (nDiff < 0)));
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: TFX: View %d: comp(%s, ",
|
|
i,
|
|
SnmpUtilOidToA(&vbl->list[vb].name)
|
|
));
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"%s, %d) = %d '%s'\n",
|
|
SnmpUtilOidToA(&mibView->viewOid),
|
|
mibView->viewOid.idLength,
|
|
nDiff,
|
|
fFoundOk?"Found":"NotFound"
|
|
));
|
|
|
|
|
|
// make sure we can obtain mib entry (if available)
|
|
if (fFoundOk && (mibView->viewType == MIB_VIEW_NORMAL)) {
|
|
|
|
// initialize local copy of error status
|
|
UINT mibStatus = SNMP_ERRORSTATUS_NOERROR;
|
|
|
|
// store index
|
|
lastViewIndex = i;
|
|
|
|
// load mib entry
|
|
VarBindToMibEntry(
|
|
tfxInfo,
|
|
&vbl->list[vb],
|
|
&mibEntry,
|
|
&mibAction,
|
|
&tblXlat,
|
|
i,
|
|
&mibStatus
|
|
);
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: TFX: VarBindToMibEntry returned %d.\n",
|
|
mibStatus
|
|
));
|
|
|
|
// successfully loaded mib entry information
|
|
fFoundOk = (mibStatus == SNMP_ERRORSTATUS_NOERROR);
|
|
|
|
// bail if not searching...
|
|
if (!fFoundOk && !fAnyOk) {
|
|
// pass up error status
|
|
*errorStatus = mibStatus;
|
|
*errorIndex = vb+1;
|
|
return; // bail...
|
|
}
|
|
}
|
|
}
|
|
|
|
// reset error status and index...
|
|
*errorStatus = SNMP_ERRORSTATUS_NOERROR;
|
|
*errorIndex = 0;
|
|
|
|
// found AND had a valid mibEntry
|
|
if (fFoundOk && mibEntry) {
|
|
// save query
|
|
MibEntryToQueryList(
|
|
mibEntry,
|
|
mibAction,
|
|
ql,
|
|
tblXlat,
|
|
i-1,
|
|
vbl,
|
|
vb,
|
|
errorStatus
|
|
);
|
|
|
|
} else if (fAnyOk){
|
|
|
|
if (lastViewIndex == -1)
|
|
lastViewIndex = tfxInfo->numViews - 1;
|
|
|
|
// not supported in any view...
|
|
SnmpUtilOidFree(&vbl->list[vb].name);
|
|
|
|
// copy varbind
|
|
if (SnmpUtilOidCpy(
|
|
&vbl->list[vb].name,
|
|
&tfxInfo->tfxViews[lastViewIndex].mibView->viewOid) == 0)
|
|
{
|
|
SNMPDBG((
|
|
SNMP_LOG_ERROR,
|
|
"SNMP: TFX: SnmpUtilOidCpy at line %d failed.\n",
|
|
__LINE__));
|
|
|
|
*errorStatus = SNMP_ERRORSTATUS_GENERR;
|
|
return; // bail...
|
|
}
|
|
|
|
// increment last element of view oid
|
|
vbl->list[vb].name.ids[(vbl->list[vb].name.idLength-1)]++;
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: TFX: changing varbind to %s.\n",
|
|
SnmpUtilOidToA(&vbl->list[vb].name)
|
|
));
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
VarBindListToQueryList(
|
|
SnmpTfxInfo * tfxInfo,
|
|
RFC1157VarBindList * vbl,
|
|
SnmpExtQueryList * ql,
|
|
UINT * errorStatus,
|
|
UINT * errorIndex
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Convert list of varbinds from incoming pdu into a list of
|
|
individual subagent queries.
|
|
|
|
Arguments:
|
|
|
|
tfxInfo - context handle.
|
|
vbl - list of varbinds in pdu.
|
|
ql - list of subagent queries.
|
|
errorStatus - used to indicate success or failure.
|
|
errorIndex - used to identify an errant varbind.
|
|
|
|
Return Values:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
UINT i; // index into varbind list
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"SNMP: TFX: processing %s request containing %d variable(s).\n",
|
|
(ql->action == MIB_ACTION_GET)
|
|
? "get"
|
|
: (ql->action == MIB_ACTION_SET)
|
|
? "set"
|
|
: (ql->action == MIB_ACTION_GETNEXT)
|
|
? "getnext"
|
|
: "unknown", vbl->len));
|
|
|
|
// initialize status return values
|
|
*errorStatus = SNMP_ERRORSTATUS_NOERROR;
|
|
*errorIndex = 0;
|
|
|
|
// process incoming variable bindings
|
|
for (i=0; i < vbl->len; i++)
|
|
{
|
|
// find varbind
|
|
VarBindToQueryList(
|
|
tfxInfo,
|
|
vbl,
|
|
ql,
|
|
i,
|
|
errorStatus,
|
|
errorIndex,
|
|
0
|
|
);
|
|
if (*errorStatus != SNMP_ERRORSTATUS_NOERROR)
|
|
{
|
|
*errorIndex = i+1; // have problem during the processing of (i+1)th varbind
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
UINT
|
|
MibStatusToSnmpStatus(
|
|
UINT mibStatus
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Translate mib status into snmp error status.
|
|
|
|
Arguments:
|
|
|
|
mibStatus - mib error code.
|
|
|
|
Return Values:
|
|
|
|
Returns snmp error status.
|
|
|
|
--*/
|
|
|
|
{
|
|
UINT errorStatus;
|
|
|
|
switch (mibStatus) {
|
|
|
|
case MIB_S_SUCCESS:
|
|
errorStatus = SNMP_ERRORSTATUS_NOERROR;
|
|
break;
|
|
|
|
case MIB_S_INVALID_PARAMETER:
|
|
errorStatus = SNMP_ERRORSTATUS_BADVALUE;
|
|
break;
|
|
|
|
case MIB_S_NOT_SUPPORTED:
|
|
case MIB_S_NO_MORE_ENTRIES:
|
|
case MIB_S_ENTRY_NOT_FOUND:
|
|
errorStatus = SNMP_ERRORSTATUS_NOSUCHNAME;
|
|
break;
|
|
|
|
default:
|
|
errorStatus = SNMP_ERRORSTATUS_GENERR;
|
|
break;
|
|
}
|
|
|
|
return errorStatus;
|
|
}
|
|
|
|
|
|
VOID
|
|
AdjustErrorIndex(
|
|
SnmpExtQuery * q,
|
|
UINT * errorIndex
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Ensure that indices match the original pdu.
|
|
|
|
Arguments:
|
|
|
|
q - subagent query.
|
|
errorIndex - used to identify an errant varbind.
|
|
|
|
Return Values:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
UINT errorIndexOld = *errorIndex;
|
|
|
|
// make sure within bounds
|
|
if (errorIndexOld && (errorIndexOld <= q->vblNum)) {
|
|
|
|
// determine proper index from xlat info
|
|
*errorIndex = q->vblXlat[errorIndexOld-1].vblIndex+1;
|
|
|
|
} else {
|
|
|
|
// default to first variable
|
|
*errorIndex = q->vblXlat[0].vblIndex+1;
|
|
}
|
|
}
|
|
|
|
|
|
BOOL
|
|
ProcessQuery(
|
|
SnmpExtQuery * q,
|
|
UINT * errorStatus,
|
|
UINT * errorIndex
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Query the subagent for requested items.
|
|
|
|
Arguments:
|
|
|
|
q - subagent query.
|
|
errorStatus - used to indicate success or failure.
|
|
errorIndex - used to identify an errant varbind.
|
|
|
|
Return Values:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
BOOL fOk = TRUE;
|
|
UINT extStatus = 0;
|
|
|
|
AsnAny * objArray;
|
|
|
|
// validate...
|
|
if (q == NULL) {
|
|
return TRUE;
|
|
}
|
|
|
|
// retrieve asn object array
|
|
objArray = (AsnAny *)(q->extData.data);
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: TFX: ProcessQuery - objArray=%lx\n",
|
|
objArray
|
|
));
|
|
|
|
__try {
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: TFX: entering subagent code ....\n"
|
|
));
|
|
// query subagent
|
|
extStatus = (UINT)(*q->extFunc)(
|
|
q->mibAction,
|
|
objArray,
|
|
errorIndex
|
|
);
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: TFX: ... subagent code completed.\n"
|
|
));
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"SNMP: TFX: subagent returned %s (e=0x%08lx,i=%d).\n",
|
|
(extStatus == MIB_S_SUCCESS)
|
|
? "MIB_S_SUCCESS"
|
|
: (extStatus == MIB_S_NO_MORE_ENTRIES)
|
|
? "MIB_S_NO_MORE_ENTRIES"
|
|
: (extStatus == MIB_S_ENTRY_NOT_FOUND)
|
|
? "MIB_S_ENTRY_NOT_FOUND"
|
|
: (extStatus == MIB_S_INVALID_PARAMETER)
|
|
? "MIB_S_INVALID_PARAMETER"
|
|
: (extStatus == MIB_S_NOT_SUPPORTED)
|
|
? "MIB_S_NOT_SUPPORTED"
|
|
: "error", extStatus, *errorIndex
|
|
));
|
|
|
|
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
|
|
|
// report exception code
|
|
extStatus = GetExceptionCode();
|
|
|
|
// disable
|
|
fOk = FALSE;
|
|
}
|
|
|
|
// save error info
|
|
SetLastError(extStatus);
|
|
|
|
// pass back translated version
|
|
*errorStatus = MibStatusToSnmpStatus(extStatus);
|
|
|
|
return fOk;
|
|
}
|
|
|
|
|
|
VOID
|
|
ProcessQueryList(
|
|
SnmpTfxInfo * tfxInfo,
|
|
SnmpExtQueryList * ql,
|
|
RFC1157VarBindList * vbl,
|
|
UINT * errorStatus,
|
|
UINT * errorIndex
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Process the query list based on request type.
|
|
|
|
Arguments:
|
|
|
|
tfxInfo - context information.
|
|
ql - list of subagent queries.
|
|
vbl - list of incoming variable bindings.
|
|
errorStatus - used to indicate success or failure.
|
|
errorIndex - used to identify an errant varbind.
|
|
|
|
Return Values:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
INT i=0; // index into query list
|
|
INT j=0; // index into query list
|
|
|
|
INT qlLen = ql->len; // save...
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"SNMP: TFX: processing %d subagent queries.\n",
|
|
qlLen
|
|
));
|
|
|
|
// sets are processed below...
|
|
if (ql->action != MIB_ACTION_SET) {
|
|
|
|
// process list of individual queries
|
|
for (i=0; (i < qlLen) && !(*errorStatus); i++ ) {
|
|
|
|
// send query to subagent
|
|
if (ProcessQuery(&ql->query[i], errorStatus, errorIndex)) {
|
|
|
|
// need to validate getnext results
|
|
if (ql->action == MIB_ACTION_GETNEXT) {
|
|
// exhaust all possibilities...
|
|
ValidateQueryList(
|
|
tfxInfo,
|
|
ql,
|
|
i,
|
|
vbl,
|
|
errorStatus,
|
|
errorIndex
|
|
);
|
|
}
|
|
|
|
// check the subagent status code returned
|
|
if (*errorStatus != SNMP_ERRORSTATUS_NOERROR) {
|
|
// adjust index to match request pdu
|
|
AdjustErrorIndex(&ql->query[i], errorIndex);
|
|
}
|
|
|
|
} else {
|
|
|
|
// subagent unable to process query
|
|
*errorStatus = SNMP_ERRORSTATUS_GENERR;
|
|
*errorIndex = 1;
|
|
// adjust index to match request pdu
|
|
AdjustErrorIndex(&ql->query[i], errorIndex);
|
|
}
|
|
}
|
|
|
|
} else {
|
|
|
|
// process all of the validate queries
|
|
for (i=0; (i < qlLen) && !(*errorStatus); i++) {
|
|
|
|
// alter query type to validate entries
|
|
ql->query[i].mibAction = MIB_ACTION_VALIDATE;
|
|
|
|
// send query to subagent
|
|
if (ProcessQuery(&ql->query[i], errorStatus, errorIndex)) {
|
|
|
|
// check the subagent status code returned
|
|
if (*errorStatus != SNMP_ERRORSTATUS_NOERROR) {
|
|
// adjust index to match request pdu
|
|
AdjustErrorIndex(&ql->query[i], errorIndex);
|
|
}
|
|
|
|
} else {
|
|
|
|
// subagent unable to process query
|
|
*errorStatus = SNMP_ERRORSTATUS_GENERR;
|
|
*errorIndex = 1;
|
|
// adjust index to match request pdu
|
|
AdjustErrorIndex(&ql->query[i], errorIndex);
|
|
}
|
|
}
|
|
|
|
// process all of the set queries
|
|
for (j=0; (j < qlLen) && !(*errorStatus); j++) {
|
|
|
|
// alter query type to set entries
|
|
ql->query[j].mibAction = MIB_ACTION_SET;
|
|
|
|
// send query to subagent
|
|
if (ProcessQuery(&ql->query[j], errorStatus, errorIndex)) {
|
|
|
|
// check the subagent status code returned
|
|
if (*errorStatus != SNMP_ERRORSTATUS_NOERROR) {
|
|
// adjust index to match request pdu
|
|
AdjustErrorIndex(&ql->query[j], errorIndex);
|
|
}
|
|
|
|
} else {
|
|
|
|
// subagent unable to process query
|
|
*errorStatus = SNMP_ERRORSTATUS_GENERR;
|
|
*errorIndex = 1;
|
|
// adjust index to match request pdu
|
|
AdjustErrorIndex(&ql->query[j], errorIndex);
|
|
}
|
|
}
|
|
|
|
// cleanup...
|
|
while (i-- > 0) {
|
|
|
|
UINT ignoreStatus = 0; // dummy values
|
|
UINT ignoreIndex = 0; // dummy values
|
|
|
|
// alter query type to set entries
|
|
ql->query[i].mibAction = MIB_ACTION_CLEANUP;
|
|
|
|
// send the cleanup request success or not
|
|
ProcessQuery(&ql->query[i], &ignoreStatus, &ignoreIndex);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
BOOL
|
|
ConstructInstanceIdentifier(
|
|
SnmpTableXlat * tblXlat,
|
|
AsnAny * objArray,
|
|
AsnObjectIdentifier * newOid,
|
|
UINT mibAction
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Convert asn value into index oid.
|
|
|
|
Arguments:
|
|
|
|
tblXlat - table translation info.
|
|
objArray - asn object array.
|
|
newOid - relative oid to return.
|
|
mibAction - action requested of subagent.
|
|
|
|
Return Values: TRUE if successful
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
UINT i;
|
|
UINT j;
|
|
UINT k;
|
|
UINT l;
|
|
UINT m;
|
|
|
|
BOOL fFixed;
|
|
BOOL fLimit;
|
|
BOOL fIndex;
|
|
|
|
UINT numItems;
|
|
|
|
SnmpMibEntry * mibEntry;
|
|
|
|
UINT * tmpIds = NULL; // prefix bug 445170
|
|
|
|
// initialize
|
|
newOid->ids = NULL;
|
|
newOid->idLength = 0;
|
|
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"SNMP: TFX: converting obj array to index via table 0x%08lx.\n",
|
|
tblXlat->txInfo
|
|
));
|
|
|
|
// retrieve root entry and entry count
|
|
numItems = tblXlat->txInfo->numIndices;
|
|
|
|
// see if the table indices are specified
|
|
fIndex = (tblXlat->txInfo->tableIndices != NULL);
|
|
|
|
// scan entries of table indices
|
|
for (i=0, j=0; i < numItems; i++) {
|
|
|
|
// get mib entry from table or directly
|
|
mibEntry = fIndex ? tblXlat->txInfo->tableIndices[i]
|
|
: &tblXlat->txInfo->tableEntry[i+1]
|
|
;
|
|
|
|
// retrieve array index
|
|
k = (mibAction == MIB_ACTION_SET)
|
|
? (UINT)(CHAR)mibEntry->mibSetBufOff
|
|
: (UINT)(CHAR)mibEntry->mibGetBufOff
|
|
;
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"SNMP: TFX: ConstructIndexIdentifier - k=%d\n",
|
|
k
|
|
));
|
|
// determine type
|
|
switch (mibEntry->mibType) {
|
|
|
|
// variable length types
|
|
case ASN_OBJECTIDENTIFIER:
|
|
|
|
// check whether this is a fixed length variable or not
|
|
fLimit = (mibEntry->mibMinimum || mibEntry->mibMaximum);
|
|
fFixed = (fLimit && (mibEntry->mibMinimum == mibEntry->mibMaximum));
|
|
|
|
// validate
|
|
if (fFixed) {
|
|
|
|
// fixed length
|
|
l = mibEntry->mibMaximum;
|
|
|
|
// allocate space
|
|
newOid->idLength += l;
|
|
|
|
tmpIds = (UINT *)SnmpUtilMemReAlloc(
|
|
newOid->ids,
|
|
newOid->idLength * sizeof(UINT)
|
|
);
|
|
if (tmpIds == NULL)
|
|
{
|
|
newOid->idLength = 0;
|
|
SnmpUtilMemFree(newOid->ids);
|
|
newOid->ids = NULL;
|
|
return FALSE;
|
|
}
|
|
newOid->ids = tmpIds;
|
|
|
|
} else {
|
|
|
|
// determine variable length of object
|
|
l = objArray[k].asnValue.object.idLength;
|
|
|
|
// allocate space
|
|
newOid->idLength += (l+1);
|
|
tmpIds = (UINT *)SnmpUtilMemReAlloc(
|
|
newOid->ids,
|
|
newOid->idLength * sizeof(UINT)
|
|
);
|
|
if (tmpIds == NULL)
|
|
{
|
|
newOid->idLength = 0;
|
|
SnmpUtilMemFree(newOid->ids);
|
|
newOid->ids = NULL;
|
|
return FALSE;
|
|
}
|
|
newOid->ids = tmpIds;
|
|
|
|
// save length
|
|
newOid->ids[j++] = l;
|
|
}
|
|
|
|
// transfer data
|
|
for (m=0; m < l; m++) {
|
|
|
|
// transfer oid element from buffer
|
|
newOid->ids[j++] = objArray[k].asnValue.object.ids[m];
|
|
}
|
|
|
|
break;
|
|
|
|
case ASN_RFC1155_OPAQUE:
|
|
case ASN_OCTETSTRING:
|
|
|
|
// check whether this is a fixed length variable or not
|
|
fLimit = (mibEntry->mibMinimum || mibEntry->mibMaximum);
|
|
fFixed = (fLimit && (mibEntry->mibMinimum == mibEntry->mibMaximum));
|
|
|
|
// validate
|
|
if (fFixed) {
|
|
|
|
// fixed length
|
|
l = mibEntry->mibMaximum;
|
|
|
|
// allocate space
|
|
newOid->idLength += l;
|
|
tmpIds = (UINT *)SnmpUtilMemReAlloc(
|
|
newOid->ids,
|
|
newOid->idLength * sizeof(UINT)
|
|
);
|
|
if (tmpIds == NULL)
|
|
{
|
|
newOid->idLength = 0;
|
|
SnmpUtilMemFree(newOid->ids);
|
|
newOid->ids = NULL;
|
|
return FALSE;
|
|
}
|
|
newOid->ids = tmpIds;
|
|
|
|
} else {
|
|
|
|
// determine variable length of object
|
|
l = objArray[k].asnValue.string.length;
|
|
|
|
// allocate space
|
|
newOid->idLength += (l+1);
|
|
tmpIds = (UINT *)SnmpUtilMemReAlloc(
|
|
newOid->ids,
|
|
newOid->idLength * sizeof(UINT)
|
|
);
|
|
if (tmpIds == NULL)
|
|
{
|
|
newOid->idLength = 0;
|
|
SnmpUtilMemFree(newOid->ids);
|
|
newOid->ids = NULL;
|
|
return FALSE;
|
|
}
|
|
newOid->ids = tmpIds;
|
|
|
|
// save length
|
|
newOid->ids[j++] = l;
|
|
}
|
|
|
|
// transfer data
|
|
for (m=0; m < l; m++) {
|
|
|
|
// convert character
|
|
newOid->ids[j++] =
|
|
(UINT)(UCHAR)objArray[k].asnValue.string.stream[m];
|
|
}
|
|
|
|
break;
|
|
|
|
// implicit fixed size
|
|
case ASN_RFC1155_IPADDRESS:
|
|
|
|
// allocate space
|
|
newOid->idLength += 4;
|
|
tmpIds = (UINT *)SnmpUtilMemReAlloc(
|
|
newOid->ids,
|
|
newOid->idLength * sizeof(UINT)
|
|
);
|
|
if (tmpIds == NULL)
|
|
{
|
|
newOid->idLength = 0;
|
|
SnmpUtilMemFree(newOid->ids);
|
|
newOid->ids = NULL;
|
|
return FALSE;
|
|
}
|
|
newOid->ids = tmpIds;
|
|
|
|
// transfer data into buffer
|
|
newOid->ids[j++] = (DWORD)(BYTE)objArray[k].asnValue.string.stream[0];
|
|
newOid->ids[j++] = (DWORD)(BYTE)objArray[k].asnValue.string.stream[1];
|
|
newOid->ids[j++] = (DWORD)(BYTE)objArray[k].asnValue.string.stream[2];
|
|
newOid->ids[j++] = (DWORD)(BYTE)objArray[k].asnValue.string.stream[3];
|
|
|
|
break;
|
|
|
|
case ASN_RFC1155_COUNTER:
|
|
case ASN_RFC1155_GAUGE:
|
|
case ASN_RFC1155_TIMETICKS:
|
|
case ASN_INTEGER:
|
|
|
|
// allocate space
|
|
newOid->idLength += 1;
|
|
tmpIds = (UINT *)SnmpUtilMemReAlloc(
|
|
newOid->ids,
|
|
newOid->idLength * sizeof(UINT)
|
|
);
|
|
if (tmpIds == NULL)
|
|
{
|
|
newOid->idLength = 0;
|
|
SnmpUtilMemFree(newOid->ids);
|
|
newOid->ids = NULL;
|
|
return FALSE;
|
|
}
|
|
newOid->ids = tmpIds;
|
|
|
|
// transfer value as integer
|
|
newOid->ids[j++] = objArray[k].asnValue.number;
|
|
break;
|
|
|
|
default:
|
|
// invalidate
|
|
j = INVALID_INDEX;
|
|
break;
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
VOID
|
|
DeleteQuery(
|
|
SnmpExtQuery * q
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Deletes individual query.
|
|
|
|
Arguments:
|
|
|
|
q - subagent query.
|
|
|
|
Return Values:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
UINT i; // index into xlat array
|
|
UINT j; // index into object array
|
|
|
|
BOOL fSet;
|
|
|
|
AsnAny * objArray;
|
|
SnmpMibEntry * mibEntry;
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: TFX: deleting query 0x%08lx.\n", q
|
|
));
|
|
|
|
// determine whether a set was requested
|
|
fSet = (q->mibAction == MIB_ACTION_SET);
|
|
|
|
// retrieve asn object array
|
|
objArray = (AsnAny *)(q->extData.data);
|
|
|
|
// free requested entries
|
|
for (i = 0; i < q->vblNum; i++ )
|
|
{
|
|
// retrieve mib entry
|
|
mibEntry = q->vblXlat[i].mibEntry;
|
|
|
|
ASSERT(mibEntry);
|
|
|
|
j = fSet ? (UINT)(CHAR)mibEntry->mibSetBufOff
|
|
: (UINT)(CHAR)mibEntry->mibGetBufOff
|
|
;
|
|
|
|
if (objArray)
|
|
SnmpUtilAsnAnyFree(&objArray[j]);
|
|
|
|
// free any followup queries
|
|
if ((q->vblXlat[i].extQuery != NULL) &&
|
|
(q->vblXlat[i].extQuery != INVALID_QUERY))
|
|
{
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: TFX: deleting followup query 0x%08lx.\n",
|
|
q->vblXlat[i].extQuery
|
|
));
|
|
|
|
// free followup query
|
|
DeleteQuery(q->vblXlat[i].extQuery);
|
|
|
|
// free query structure itself
|
|
SnmpUtilMemFree(q->vblXlat[i].extQuery);
|
|
}
|
|
}
|
|
|
|
q->vblNum = 0;
|
|
|
|
|
|
// free indices
|
|
if (q->tblXlat && objArray)
|
|
{
|
|
|
|
BOOL fIndex;
|
|
|
|
// see if the table indices are specified
|
|
fIndex = (q->tblXlat->txInfo->tableIndices != NULL);
|
|
|
|
// free the individual indices
|
|
for (i = 0; i < q->tblXlat->txInfo->numIndices; i++)
|
|
{
|
|
|
|
// get mib entry from table or directly from entry
|
|
mibEntry = fIndex ? q->tblXlat->txInfo->tableIndices[i]
|
|
: &q->tblXlat->txInfo->tableEntry[i+1]
|
|
;
|
|
|
|
ASSERT(mibEntry);
|
|
|
|
// determine the buffer offset used
|
|
j = fSet ? (UINT)(CHAR)mibEntry->mibSetBufOff
|
|
: (UINT)(CHAR)mibEntry->mibGetBufOff
|
|
;
|
|
|
|
// free individual index
|
|
SnmpUtilAsnAnyFree(&objArray[j]);
|
|
}
|
|
}
|
|
|
|
|
|
// free buffer
|
|
SnmpUtilMemFree(objArray);
|
|
|
|
// avoid double freeing
|
|
q->extData.data = NULL;
|
|
|
|
// free table info
|
|
if (q->tblXlat) {
|
|
|
|
// free object identifier
|
|
SnmpUtilOidFree(&q->tblXlat->txOid);
|
|
|
|
// free the xlat structure
|
|
SnmpUtilMemFree(q->tblXlat);
|
|
|
|
// avoid double freeing
|
|
q->tblXlat = NULL;
|
|
}
|
|
|
|
// free translation info
|
|
SnmpUtilMemFree(q->vblXlat);
|
|
|
|
// avoid double freeing
|
|
q->vblXlat = NULL;
|
|
}
|
|
|
|
|
|
VOID
|
|
DeleteQueryList(
|
|
SnmpExtQueryList * ql
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Deletes query list.
|
|
|
|
Arguments:
|
|
|
|
ql - list of subagent queries.
|
|
|
|
Return Values:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
UINT q; // index into query list
|
|
|
|
// process queries
|
|
for (q=0; q < ql->len; q++) {
|
|
|
|
// delete query
|
|
DeleteQuery(&ql->query[q]);
|
|
}
|
|
|
|
// free query list
|
|
SnmpUtilMemFree(ql->query);
|
|
}
|
|
|
|
|
|
VOID
|
|
QueryToVarBindList(
|
|
SnmpTfxInfo * tfxInfo,
|
|
SnmpExtQuery * q,
|
|
RFC1157VarBindList * vbl,
|
|
UINT * errorStatus,
|
|
UINT * errorIndex
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Convert query back into varbind.
|
|
|
|
Arguments:
|
|
|
|
tfxInfo - context info
|
|
q - subagent query.
|
|
vbl - list of varbinds in outgoing pdu.
|
|
|
|
Return Values:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
UINT i=0;
|
|
UINT j=0;
|
|
UINT k=0;
|
|
UINT l=0;
|
|
|
|
BOOL fSet;
|
|
|
|
AsnAny * objArray;
|
|
SnmpMibEntry * mibEntry;
|
|
|
|
AsnObjectIdentifier idxOid;
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: TFX: converting query 0x%08lx to varbinds.\n", q
|
|
));
|
|
|
|
// determine whether a set was requested
|
|
fSet = (q->mibAction == MIB_ACTION_SET);
|
|
|
|
// retrieve asn object array
|
|
objArray = (AsnAny *)(q->extData.data);
|
|
|
|
// copy requested entries
|
|
for (j = 0; j < q->vblNum; j++) {
|
|
// process followup query
|
|
if (q->vblXlat[j].extQuery != NULL) {
|
|
|
|
if (q->vblXlat[j].extQuery != INVALID_QUERY) {
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: TFX: processing followup query 0x%08lx.\n",
|
|
q->vblXlat[j].extQuery
|
|
));
|
|
|
|
|
|
QueryToVarBindList(
|
|
tfxInfo,
|
|
q->vblXlat[j].extQuery,
|
|
vbl,
|
|
errorStatus,
|
|
errorIndex
|
|
);
|
|
|
|
if (*errorStatus != SNMP_ERRORSTATUS_NOERROR)
|
|
return; // bail...
|
|
else
|
|
continue; // skip...
|
|
|
|
} else {
|
|
|
|
i = q->vblXlat[j].vblIndex;
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"SNMP: TFX: returning oid %s without reassembly.\n",
|
|
SnmpUtilOidToA(&vbl->list[i].name)
|
|
));
|
|
|
|
continue; // skip...
|
|
}
|
|
}
|
|
|
|
// retrieve index
|
|
i = q->vblXlat[j].vblIndex;
|
|
|
|
// retrieve mib entry for requested item
|
|
mibEntry = q->vblXlat[j].mibEntry;
|
|
|
|
k = fSet ? (UINT)(CHAR)mibEntry->mibSetBufOff
|
|
: (UINT)(CHAR)mibEntry->mibGetBufOff
|
|
;
|
|
|
|
// free original variable
|
|
SnmpUtilVarBindFree(&vbl->list[i]);
|
|
|
|
// copy the asn value first
|
|
if (SnmpUtilAsnAnyCpy(&vbl->list[i].value, &objArray[k]) == 0)
|
|
{
|
|
// report memory allocation problem
|
|
*errorIndex = i+1; // failed in (i+1)th varbind
|
|
*errorStatus = SNMP_ERRORSTATUS_GENERR;
|
|
SNMPDBG((
|
|
SNMP_LOG_ERROR,
|
|
"SNMP: TFX: SnmpUtilAsnAnyCpy at line %d failed on the %d th varbind.\n",
|
|
__LINE__, i+1
|
|
));
|
|
return; // bail...
|
|
}
|
|
|
|
// copy root oid of view
|
|
if (SnmpUtilOidCpy(
|
|
&vbl->list[i].name,
|
|
&tfxInfo->tfxViews[(q->vblXlat[j].vlIndex)].mibView->viewOid) == 0)
|
|
{
|
|
// report memory allocation problem
|
|
*errorIndex = i+1; // failed in (i+1)th varbind
|
|
*errorStatus = SNMP_ERRORSTATUS_GENERR;
|
|
SNMPDBG((
|
|
SNMP_LOG_ERROR,
|
|
"SNMP: TFX: SnmpUtilOidCpy at line %d failed on the %d th varbind.\n",
|
|
__LINE__, i+1
|
|
));
|
|
return; // bail...
|
|
}
|
|
|
|
// copy oid of variable
|
|
if (SnmpUtilOidAppend(
|
|
&vbl->list[i].name,
|
|
&mibEntry->mibOid) == 0)
|
|
{
|
|
// report memory allocation problem
|
|
*errorIndex = i+1; // failed in (i+1)th varbind
|
|
*errorStatus = SNMP_ERRORSTATUS_GENERR;
|
|
SNMPDBG((
|
|
SNMP_LOG_ERROR,
|
|
"SNMP: TFX: SnmpUtilOidAppend at line %d failed on the %d th varbind.\n",
|
|
__LINE__, i+1
|
|
));
|
|
return; // bail...
|
|
}
|
|
|
|
// copy table index
|
|
if (q->tblXlat) {
|
|
|
|
// convert value to oid
|
|
if (ConstructInstanceIdentifier(q->tblXlat, objArray, &idxOid, q->mibAction) == FALSE)
|
|
{
|
|
// report memory allocation problem
|
|
*errorIndex = i+1; // failed in (i+1)th varbind
|
|
*errorStatus = SNMP_ERRORSTATUS_GENERR;
|
|
SNMPDBG((
|
|
SNMP_LOG_ERROR,
|
|
"SNMP: TFX: ConstructInstanceIdentifier failed with %d th varbind.\n",
|
|
i+1
|
|
));
|
|
return; // bail...
|
|
}
|
|
|
|
// append oid to object name
|
|
if (SnmpUtilOidAppend(&vbl->list[i].name, &idxOid) == 0)
|
|
{
|
|
// free temp oid
|
|
SnmpUtilOidFree(&idxOid);
|
|
|
|
// report memory allocation problem
|
|
*errorIndex = i+1; // failed in (i+1)th varbind
|
|
*errorStatus = SNMP_ERRORSTATUS_GENERR;
|
|
SNMPDBG((
|
|
SNMP_LOG_ERROR,
|
|
"SNMP: TFX: SnmpUtilOidAppend at line %d failed on the %d th varbind.\n",
|
|
__LINE__, i+1
|
|
));
|
|
return; // bail...
|
|
}
|
|
|
|
// free temp oid
|
|
SnmpUtilOidFree(&idxOid);
|
|
}
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"SNMP: TFX: returning oid %s.\n",
|
|
SnmpUtilOidToA(&vbl->list[i].name)
|
|
));
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
QueryListToVarBindList(
|
|
SnmpTfxInfo * tfxInfo,
|
|
SnmpExtQueryList * ql,
|
|
RFC1157VarBindList * vbl,
|
|
UINT * errorStatus,
|
|
UINT * errorIndex
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Convert query list back into outgoing varbinds.
|
|
|
|
Arguments:
|
|
|
|
tfxInfo - context information.
|
|
ql - list of subagent queries.
|
|
vbl - list of varbinds in outgoing pdu.
|
|
errorStatus - used to indicate success or failure.
|
|
errorIndex - used to identify an errant varbind.
|
|
|
|
Return Values:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
UINT q; // index into queue list
|
|
UINT vb; // index into queue varbind list
|
|
UINT i; // index into original varbind list
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"SNMP: TFX: request %s, errorStatus=%s, errorIndex=%d.\n",
|
|
(*errorStatus == SNMP_ERRORSTATUS_NOERROR)
|
|
? "succeeded"
|
|
: "failed",
|
|
(*errorStatus == SNMP_ERRORSTATUS_NOERROR)
|
|
? "NOERROR"
|
|
: (*errorStatus == SNMP_ERRORSTATUS_NOSUCHNAME)
|
|
? "NOSUCHNAME"
|
|
: (*errorStatus == SNMP_ERRORSTATUS_BADVALUE)
|
|
? "BADVALUE"
|
|
: (*errorStatus == SNMP_ERRORSTATUS_READONLY)
|
|
? "READONLY"
|
|
: (*errorStatus == SNMP_ERRORSTATUS_TOOBIG)
|
|
? "TOOBIG"
|
|
: "GENERR", *errorIndex
|
|
));
|
|
|
|
// only convert back if error not reported
|
|
if (*errorStatus == SNMP_ERRORSTATUS_NOERROR) {
|
|
|
|
// process queries
|
|
for (q=0; q < ql->len; q++) {
|
|
|
|
// translate query data
|
|
QueryToVarBindList(tfxInfo, &ql->query[q], vbl, errorStatus, errorIndex);
|
|
if (*errorStatus != SNMP_ERRORSTATUS_NOERROR)
|
|
break;
|
|
}
|
|
}
|
|
|
|
// free
|
|
DeleteQueryList(ql);
|
|
}
|
|
|
|
VOID
|
|
ValidateQueryList(
|
|
SnmpTfxInfo * tfxInfo,
|
|
SnmpExtQueryList * ql,
|
|
UINT q,
|
|
RFC1157VarBindList * vbl,
|
|
UINT * errorStatus,
|
|
UINT * errorIndex
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Validate getnext results and re-query if necessary.
|
|
|
|
Arguments:
|
|
|
|
tfxInfo - context information.
|
|
ql - list of subagent queries.
|
|
q - subagent query of interest.
|
|
vbl - list of bindings in incoming pdu.
|
|
errorStatus - used to indicate success or failure.
|
|
errorIndex - used to identify an errant varbind.
|
|
|
|
Return Values:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
UINT i;
|
|
UINT j;
|
|
|
|
SnmpExtQueryList tmpQl;
|
|
|
|
UINT vlIndex;
|
|
UINT vblIndex;
|
|
UINT mibAction;
|
|
UINT mibStatus;
|
|
SnmpMibEntry * mibEntry;
|
|
SnmpTableXlat * tblXlat;
|
|
RFC1157VarBindList tmpVbl;
|
|
BOOL fFoundOk = FALSE;
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"SNMP: TFX: verifying results of query 0x%08lx.\n", &ql->query[q]
|
|
));
|
|
|
|
// bail on any error other than no such name
|
|
if (*errorStatus != SNMP_ERRORSTATUS_NOSUCHNAME) {
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"SNMP: TFX: *errorStatus != SNMP_ERRORSTATUS_NOSUCHNAME, *errorStatus = %d.\n",
|
|
*errorStatus
|
|
));
|
|
|
|
return; // bail...
|
|
}
|
|
|
|
// scan query list updating variables
|
|
for (i=0; i < ql->query[q].vblNum; i++) {
|
|
|
|
// initialize
|
|
mibEntry = ql->query[q].vblXlat[i].mibEntry;
|
|
vlIndex = ql->query[q].vblXlat[i].vlIndex;
|
|
j = ql->query[q].vblXlat[i].vlIndex;
|
|
|
|
tblXlat = NULL;
|
|
mibAction = MIB_ACTION_GETNEXT;
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"SNMP: TFX: ValidateQueryList; next of %s.\n",
|
|
SnmpUtilOidToA(&mibEntry->mibOid)
|
|
));
|
|
|
|
// next...
|
|
FindNextMibEntry(
|
|
tfxInfo,
|
|
NULL,
|
|
&mibEntry,
|
|
&mibAction,
|
|
&tblXlat,
|
|
vlIndex,
|
|
errorStatus
|
|
);
|
|
|
|
while (*errorStatus == SNMP_ERRORSTATUS_NOERROR) {
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"SNMP: TFX: constructing followup to query 0x%08lx:\n"
|
|
"SNMP: TFX: \tmibEntry=0x%08lx\n"
|
|
"SNMP: TFX: \ttblXlat =0x%08lx\n",
|
|
&ql->query[q],
|
|
mibEntry,
|
|
tblXlat
|
|
));
|
|
|
|
// initialize
|
|
tmpQl.len = 0;
|
|
tmpQl.query = NULL;
|
|
tmpQl.action = MIB_ACTION_GETNEXT;
|
|
|
|
// create query
|
|
MibEntryToQueryList(
|
|
mibEntry,
|
|
mibAction,
|
|
&tmpQl,
|
|
tblXlat,
|
|
vlIndex,
|
|
NULL,
|
|
ql->query[q].vblXlat[i].vblIndex,
|
|
errorStatus
|
|
);
|
|
|
|
if (*errorStatus != SNMP_ERRORSTATUS_NOERROR) {
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_ERROR,
|
|
"SNMP: TFX: ValidateQueryList; MibEntryToQueryList returned %d.\n",
|
|
*errorStatus
|
|
));
|
|
|
|
// delete if necessary
|
|
DeleteQueryList(&tmpQl);
|
|
|
|
return; // bail...
|
|
}
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"SNMP: TFX: processing followup query 0x%08lx.\n",
|
|
tmpQl.query
|
|
));
|
|
|
|
// perform query with new oid
|
|
ProcessQuery(tmpQl.query, errorStatus, errorIndex);
|
|
|
|
// calculate results of query
|
|
if (*errorStatus == SNMP_ERRORSTATUS_NOERROR) {
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"SNMP: TFX: saving followup 0x%08lx in query 0x%08lx.\n",
|
|
tmpQl.query, &ql->query[q]
|
|
));
|
|
|
|
// copy query for reassembly purposes
|
|
ql->query[q].vblXlat[i].extQuery = tmpQl.query;
|
|
|
|
break; // process next varbind...
|
|
|
|
} else if (*errorStatus != SNMP_ERRORSTATUS_NOSUCHNAME) {
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"SNMP: TFX: could not process followup.\n"
|
|
));
|
|
|
|
// delete...
|
|
DeleteQueryList(&tmpQl);
|
|
|
|
return; // bail...
|
|
}
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"SNMP: TFX: re-processing followup to query 0x%08lx.\n",
|
|
&ql->query[q]
|
|
));
|
|
|
|
// delete...
|
|
DeleteQueryList(&tmpQl);
|
|
|
|
// re-initialize and continue...
|
|
*errorStatus = SNMP_ERRORSTATUS_NOERROR;
|
|
tblXlat = NULL;
|
|
mibAction = MIB_ACTION_GETNEXT;
|
|
|
|
// next...
|
|
FindNextMibEntry(
|
|
tfxInfo,
|
|
NULL,
|
|
&mibEntry,
|
|
&mibAction,
|
|
&tblXlat,
|
|
vlIndex,
|
|
errorStatus
|
|
);
|
|
}
|
|
|
|
// NOTE: if we break from the above while loop,
|
|
// *errorStatus will be SNMP_ERRORSTATUS_NOERROR
|
|
|
|
// attempt to query next supported subagent view
|
|
if (*errorStatus == SNMP_ERRORSTATUS_NOSUCHNAME) {
|
|
|
|
// retrieve variable binding list index
|
|
vblIndex = ql->query[q].vblXlat[i].vblIndex;
|
|
|
|
// release old variable binding
|
|
SnmpUtilVarBindFree(&vbl->list[vblIndex]);
|
|
|
|
// copy varbind
|
|
if (! SnmpUtilOidCpy(&vbl->list[vblIndex].name,
|
|
&tfxInfo->tfxViews[j].mibView->viewOid) )
|
|
{
|
|
SNMPDBG((
|
|
SNMP_LOG_ERROR,
|
|
"SNMP: TFX: ValidateQueryList; SnmpUtilOidCpy failed.\n"
|
|
));
|
|
|
|
*errorStatus = SNMP_ERRORSTATUS_GENERR;
|
|
|
|
return; // bail...
|
|
}
|
|
|
|
// increment last sub-identifier of view oid
|
|
vbl->list[vblIndex].name.ids[vbl->list[vblIndex].name.idLength-1]++;
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"SNMP: TFX: query out of view. Pass up %s to service.\n",
|
|
SnmpUtilOidToA(&vbl->list[vblIndex].name)
|
|
));
|
|
|
|
// this query goes outside the MIB view.
|
|
// varbind is set (above) to the first OID outside this view, so let the master agent
|
|
// handle the switch between views.
|
|
|
|
// let QueryToVarBindList() knows that this SnmpVarBindXlat is
|
|
// not valid for reassembly purpose.
|
|
ql->query[q].vblXlat[i].extQuery = INVALID_QUERY;
|
|
|
|
*errorStatus = SNMP_ERRORSTATUS_NOERROR;
|
|
|
|
continue; // process next varbind...
|
|
|
|
} else if (*errorStatus != SNMP_ERRORSTATUS_NOERROR) {
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_ERROR,
|
|
"SNMP: TFX: ValidateQueryList; FindNextMibEntry returned %d.\n",
|
|
*errorStatus
|
|
));
|
|
|
|
return; // bail...
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
SnmpTfxInfo *
|
|
AllocTfxInfo(
|
|
)
|
|
{
|
|
// simply return results from generic memory allocation
|
|
return (SnmpTfxInfo *)SnmpUtilMemAlloc(sizeof(SnmpTfxInfo));
|
|
}
|
|
|
|
|
|
VOID
|
|
FreeTfxInfo(
|
|
SnmpTfxInfo * tfxInfo
|
|
)
|
|
{
|
|
UINT i;
|
|
// prefix bug 445171
|
|
if (tfxInfo == NULL) {
|
|
return;
|
|
}
|
|
if (tfxInfo->tfxViews == NULL)
|
|
{
|
|
SnmpUtilMemFree(tfxInfo);
|
|
return;
|
|
}
|
|
|
|
// walk through list of views
|
|
for (i=0; (i < tfxInfo->numViews); i++) {
|
|
|
|
// release memory for view hash tables
|
|
FreeHashTable(tfxInfo->tfxViews[i].hashTable);
|
|
}
|
|
SnmpUtilMemFree(tfxInfo->tfxViews);
|
|
SnmpUtilMemFree(tfxInfo);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// //
|
|
// Public Procedures //
|
|
// //
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
SnmpTfxHandle
|
|
SNMP_FUNC_TYPE
|
|
SnmpTfxOpen(
|
|
DWORD numViews,
|
|
SnmpMibView * supportedViews
|
|
)
|
|
{
|
|
UINT i,j;
|
|
BOOL fOk;
|
|
SnmpTfxInfo * tfxInfo = NULL;
|
|
|
|
// validate parameters
|
|
if ((numViews == 0) ||
|
|
(supportedViews == NULL)) {
|
|
return NULL;
|
|
}
|
|
|
|
// allocate structure
|
|
tfxInfo = AllocTfxInfo();
|
|
|
|
// validate pointer
|
|
if (tfxInfo == NULL) {
|
|
return NULL;
|
|
}
|
|
|
|
// copy number of views
|
|
tfxInfo->numViews = numViews;
|
|
|
|
// allocate individual view structures
|
|
tfxInfo->tfxViews = SnmpUtilMemAlloc(
|
|
tfxInfo->numViews * sizeof(SnmpTfxView)
|
|
);
|
|
|
|
// initialize status
|
|
fOk = (tfxInfo->tfxViews != NULL);
|
|
|
|
// initialize each view structure
|
|
for (i=0; (i < tfxInfo->numViews) && fOk; i++) {
|
|
|
|
SnmpHashNode ** tmpHashTable;
|
|
|
|
// initialize individual view list entry
|
|
tmpHashTable = AllocHashTable(&supportedViews[i]);
|
|
|
|
// initialize status
|
|
fOk = (tmpHashTable != NULL);
|
|
|
|
// validate
|
|
if (fOk) {
|
|
|
|
// save a pointer into the subagent view list
|
|
tfxInfo->tfxViews[i].mibView = &supportedViews[i];
|
|
|
|
// save newly allocated view hash table
|
|
tfxInfo->tfxViews[i].hashTable = tmpHashTable;
|
|
}
|
|
}
|
|
|
|
// validate
|
|
if (fOk) {
|
|
|
|
SnmpTfxView tmpTfxView;
|
|
|
|
// make sure views are sorted
|
|
for (i=0; (i < tfxInfo->numViews); i++) {
|
|
|
|
for(j=i+1; (j < tfxInfo->numViews); j++) {
|
|
|
|
// in lexographic order?
|
|
if (0 < SnmpUtilOidCmp(
|
|
&(tfxInfo->tfxViews[i].mibView->viewOid),
|
|
&(tfxInfo->tfxViews[j].mibView->viewOid))) {
|
|
// no, swap...
|
|
tmpTfxView = tfxInfo->tfxViews[i];
|
|
tfxInfo->tfxViews[i] = tfxInfo->tfxViews[j];
|
|
tfxInfo->tfxViews[i] = tmpTfxView;
|
|
}
|
|
}
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: TFX: Adding view [%d] %s.\n",
|
|
tfxInfo->tfxViews[i].mibView->viewOid.idLength,
|
|
SnmpUtilOidToA(&(tfxInfo->tfxViews[i].mibView->viewOid))
|
|
));
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// free structure
|
|
FreeTfxInfo(tfxInfo);
|
|
|
|
// reinitialize
|
|
tfxInfo = NULL;
|
|
}
|
|
|
|
return (LPVOID)tfxInfo;
|
|
}
|
|
|
|
SNMPAPI
|
|
SNMP_FUNC_TYPE
|
|
SnmpTfxQuery(
|
|
SnmpTfxHandle tfxHandle,
|
|
BYTE requestType,
|
|
RFC1157VarBindList * vbl,
|
|
AsnInteger * errorStatus,
|
|
AsnInteger * errorIndex
|
|
)
|
|
{
|
|
SnmpExtQueryList ql;
|
|
SnmpTfxInfo *tfxInfo = tfxHandle;
|
|
int i;
|
|
|
|
// initialize
|
|
ql.query = NULL;
|
|
ql.len = 0;
|
|
ql.action = requestType;
|
|
|
|
// disassemble varbinds
|
|
VarBindListToQueryList(
|
|
(SnmpTfxInfo*)tfxHandle,
|
|
vbl,
|
|
&ql,
|
|
errorStatus,
|
|
errorIndex
|
|
);
|
|
|
|
// process queries
|
|
ProcessQueryList(
|
|
(SnmpTfxInfo*)tfxHandle,
|
|
&ql,
|
|
vbl,
|
|
errorStatus,
|
|
errorIndex
|
|
);
|
|
|
|
// reassemble varbinds
|
|
QueryListToVarBindList(
|
|
(SnmpTfxInfo*)tfxHandle,
|
|
&ql,
|
|
vbl,
|
|
errorStatus,
|
|
errorIndex
|
|
);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
VOID
|
|
SNMP_FUNC_TYPE
|
|
SnmpTfxClose(
|
|
SnmpTfxHandle tfxHandle
|
|
)
|
|
{
|
|
// simply treat as info and release
|
|
FreeTfxInfo((SnmpTfxInfo *)tfxHandle);
|
|
}
|