mirror of https://github.com/lianthony/NT4.0
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.
3511 lines
88 KiB
3511 lines
88 KiB
/*++
|
|
|
|
Copyright (c) 1992-1996 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
procreq.c
|
|
|
|
Abstract:
|
|
|
|
Provides SNMP message dispatch/processing functionality for Proxy Agent.
|
|
|
|
Environment:
|
|
|
|
User Mode - Win32
|
|
|
|
Revision History:
|
|
|
|
10-May-1996 DonRyan
|
|
Removed banner from Technology Dynamics, Inc.
|
|
|
|
--*/
|
|
|
|
//--------------------------- WINDOWS DEPENDENCIES --------------------------
|
|
|
|
//--------------------------- STANDARD DEPENDENCIES -- #include<xxxxx.h> ----
|
|
|
|
#include <windows.h>
|
|
|
|
#include <winsock.h>
|
|
#include <wsipx.h>
|
|
|
|
#include <errno.h>
|
|
#include <stdio.h>
|
|
#include <process.h>
|
|
#include <string.h>
|
|
|
|
|
|
//--------------------------- MODULE DEPENDENCIES -- #include"xxxxx.h" ------
|
|
|
|
#include <snmp.h>
|
|
#include <snmputil.h>
|
|
#include "..\common\wellknow.h"
|
|
|
|
#include "regconf.h"
|
|
|
|
//--------------------------- SELF-DEPENDENCY -- ONE #include"module.h" -----
|
|
|
|
//--------------------------- PUBLIC VARIABLES --(same as in module.h file)--
|
|
|
|
extern DWORD platformId;
|
|
|
|
|
|
//--------------------------- PRIVATE CONSTANTS -----------------------------
|
|
|
|
#define SGTTimeout ((DWORD)3600000)
|
|
|
|
#define HASH_TABLE_SIZE 101
|
|
#define HASH_TABLE_RADIX 18
|
|
|
|
#define INVALID_INDEX ((DWORD)(-1))
|
|
|
|
//--------------------------- PRIVATE STRUCTS -------------------------------
|
|
|
|
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;
|
|
|
|
typedef struct _SnmpExtQueryList {
|
|
|
|
SnmpExtQuery * query; // list of subagent queries
|
|
UINT len; // number of queries in list
|
|
UINT action; // original query request
|
|
|
|
} SnmpExtQueryList;
|
|
|
|
//--------------------------- PRIVATE VARIABLES -----------------------------
|
|
|
|
static UINT *vl = NULL; // list of extension agent views
|
|
static UINT vlLen = 0; // length of the above view list
|
|
|
|
//--------------------------- PRIVATE PROTOTYPES ----------------------------
|
|
|
|
int gethostname(OUT char *,IN int );
|
|
void dp_ipx(int, char *, SOCKADDR_IPX *, char *);
|
|
|
|
SNMPAPI
|
|
SNMP_FUNC_TYPE
|
|
SnmpUtilAsnAnyFree(
|
|
AsnAny * asnAny
|
|
);
|
|
|
|
SNMPAPI
|
|
SNMP_FUNC_TYPE
|
|
SnmpUtilAsnAnyCpy(
|
|
AsnAny * asnDst,
|
|
AsnAny * asnSrc
|
|
);
|
|
|
|
VOID
|
|
chkql(
|
|
SnmpExtQueryList * ql,
|
|
UINT q,
|
|
UINT * errorStatus,
|
|
UINT * errorIndex
|
|
);
|
|
|
|
//--------------------------- PRIVATE PROCEDURES ----------------------------
|
|
|
|
#define bzero(lp, size) (void)memset(lp, 0, size)
|
|
|
|
VOID
|
|
initvl(
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Create lexographically sorted list of initialized subagents.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Values:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
UINT i;
|
|
UINT j;
|
|
UINT temp;
|
|
|
|
SNMPDBG((SNMP_LOG_VERBOSE, "SNMP: PDU: initializing view list.\n"));
|
|
|
|
// allocate an index for each registered subagent
|
|
vl = (INT *)SnmpUtilMemAlloc(extAgentsLen * sizeof(INT));
|
|
|
|
// scan through list of registered subagents
|
|
for (i=0, vlLen=0; i < (UINT)extAgentsLen; i++) {
|
|
|
|
// flag if initialized
|
|
if (extAgents[i].fInitedOk) {
|
|
|
|
// save index
|
|
vl[vlLen++] = i;
|
|
}
|
|
}
|
|
|
|
// sort these indexes...
|
|
for (i=0; i < vlLen; i++) {
|
|
|
|
for(j=i+1; j < vlLen; j++) {
|
|
|
|
// in lexographic order?
|
|
if (0 < SnmpUtilOidCmp(
|
|
&(extAgents[vl[i]].supportedView.viewOid),
|
|
&(extAgents[vl[j]].supportedView.viewOid))) {
|
|
// no, swap...
|
|
temp = vl[i];
|
|
vl[i] = vl[j];
|
|
vl[j] = temp;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
UINT
|
|
mkhash(
|
|
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);
|
|
}
|
|
|
|
|
|
BOOL
|
|
initht(
|
|
CfgExtAgents * extInfo
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Initializes subagent hash table.
|
|
|
|
Arguments:
|
|
|
|
extInfo - subagent information.
|
|
|
|
Return Values:
|
|
|
|
Returns true if initialized successfully.
|
|
|
|
--*/
|
|
|
|
{
|
|
UINT i;
|
|
UINT j;
|
|
|
|
UINT numItems;
|
|
BOOL fInitedOk;
|
|
|
|
SnmpMibEntry * mibEntry;
|
|
SnmpHashNode * hashNode;
|
|
SnmpHashNode ** hashTable = NULL;
|
|
|
|
// determine how many items supported in view
|
|
numItems = extInfo->supportedView.viewScalars.len;
|
|
|
|
// load the first entry in the supported view
|
|
mibEntry = extInfo->supportedView.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: PDU: 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 = mkhash(&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: PDU: 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: PDU: 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: PDU: %s initialized hash table 0x%08lx.\n",
|
|
fInitedOk ? "successfully" : "unsuccessfully",
|
|
hashTable
|
|
));
|
|
|
|
if (fInitedOk) {
|
|
|
|
// save extension hash table
|
|
extInfo->hashTable = hashTable;
|
|
|
|
} else if (hashTable) {
|
|
|
|
SnmpHashNode * nextNode;
|
|
|
|
// 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->nextEntry) {
|
|
|
|
// save pointer to next node
|
|
nextNode = hashNode->nextEntry;
|
|
|
|
// free current node
|
|
SnmpUtilMemFree(hashNode);
|
|
|
|
// retrieve next
|
|
hashNode = nextNode;
|
|
}
|
|
|
|
// free last node
|
|
SnmpUtilMemFree(hashNode);
|
|
}
|
|
}
|
|
|
|
return fInitedOk;
|
|
}
|
|
|
|
|
|
VOID
|
|
dohash(
|
|
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;
|
|
SnmpMibEntry * newEntry;
|
|
SnmpHashNode * hashNode;
|
|
|
|
// create index
|
|
i = mkhash(hashOid);
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: PDU: 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: PDU: searching hash node 0x%08lx (mibe=0x%08lx).\n",
|
|
hashNode, hashNode->mibEntry
|
|
));
|
|
|
|
// retrieve saved mib entry
|
|
newEntry = hashNode->mibEntry;
|
|
|
|
// make sure that the oid matches
|
|
if (!SnmpUtilOidCmp(&newEntry->mibOid, hashOid)) {
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: PDU: returning mib entry 0x%08lx.\n",
|
|
hashNode->mibEntry
|
|
));
|
|
|
|
// return node data
|
|
*mibEntry = hashNode->mibEntry;
|
|
return;
|
|
}
|
|
|
|
// check next node
|
|
hashNode = hashNode->nextEntry;
|
|
}
|
|
}
|
|
|
|
|
|
BOOL
|
|
chkidx(
|
|
AsnObjectIdentifier * indexOid,
|
|
SnmpMibEntryList * indexInfo
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Validates that oid can be successfully parsed into index entries.
|
|
|
|
Arguments:
|
|
|
|
indexOid - object indentifier of potential index.
|
|
indexInfo - information describing syntax of index.
|
|
|
|
Return Values:
|
|
|
|
Returns true if parsing succeeded.
|
|
|
|
--*/
|
|
|
|
{
|
|
UINT i = 0;
|
|
UINT j = 0;
|
|
|
|
BOOL fOk;
|
|
|
|
BOOL fFixed;
|
|
BOOL fLimit;
|
|
|
|
SnmpMibEntry * mibEntry;
|
|
|
|
// retrieve root entry
|
|
mibEntry = indexInfo->list;
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: PDU: validating index %s via table 0x%08lx.\n",
|
|
SnmpUtilOidToA(indexOid), mibEntry
|
|
));
|
|
|
|
// next
|
|
mibEntry++;
|
|
|
|
// scan mib entries of table indices ensuring match of given oid
|
|
for (; (i < indexInfo->len) && (j < indexOid->idLength); i++, mibEntry++) {
|
|
|
|
// 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;
|
|
}
|
|
}
|
|
|
|
// check whether all of the index items could be parsed
|
|
fOk = ((i <= indexInfo->len) && (j == indexOid->idLength));
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: PDU: %s index num=%d len=%d (expected num=%d len=%d).\n",
|
|
fOk ? "valid" : "invalid", i, j, indexInfo->len, indexOid->idLength
|
|
));
|
|
|
|
return fOk;
|
|
}
|
|
|
|
|
|
VOID
|
|
chkasn(
|
|
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: PDU: 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 avaiable for reading
|
|
*errorStatus = SNMP_ERRORSTATUS_NOSUCHNAME;
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: PDU: 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 avaiable for writing
|
|
*errorStatus = SNMP_ERRORSTATUS_NOSUCHNAME;
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: PDU: entry 0x%08lx not write-enabled.\n",
|
|
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: PDU: value is %s using entry 0x%08lx.\n",
|
|
fOk ? "valid" : "invalid", mibEntry
|
|
));
|
|
|
|
// report results
|
|
*errorStatus = fOk
|
|
? SNMP_ERRORSTATUS_NOERROR
|
|
: SNMP_ERRORSTATUS_BADVALUE
|
|
;
|
|
}
|
|
|
|
|
|
VOID
|
|
findme(
|
|
RFC1157VarBind * vb,
|
|
SnmpMibEntry ** mibEntry,
|
|
UINT * mibAction,
|
|
SnmpTableXlat ** tblXlat,
|
|
UINT vlIndex,
|
|
UINT * errorStatus
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Locates mib entry associated with given varbind.
|
|
|
|
Arguments:
|
|
|
|
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;
|
|
|
|
AsnObjectIdentifier hashOid;
|
|
AsnObjectIdentifier indexOid;
|
|
AsnObjectIdentifier * viewOid;
|
|
|
|
SnmpMibTable * viewTables;
|
|
|
|
SnmpMibEntry * newEntry = NULL;
|
|
SnmpTableXlat * newXlat = NULL;
|
|
|
|
CfgExtAgents * extInfo = &extAgents[vl[vlIndex]];
|
|
|
|
// initialize
|
|
*mibEntry = NULL;
|
|
*tblXlat = NULL;
|
|
|
|
// validate hash table
|
|
if (!extInfo->hashTable) {
|
|
// initialize hash table
|
|
if (!initht(extInfo)) {
|
|
// report a general failure
|
|
*errorStatus = SNMP_ERRORSTATUS_GENERR;
|
|
return; // bail...
|
|
}
|
|
}
|
|
|
|
// retrieve the view object identifier
|
|
viewOid = &extInfo->supportedView.viewOid;
|
|
|
|
// if the prefix exactly matchs it is root oid
|
|
if (!SnmpUtilOidCmp(&vb->name, viewOid)) {
|
|
SNMPDBG((SNMP_LOG_VERBOSE, "SNMP: PDU: 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: PDU: 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
|
|
dohash(&hashOid, extInfo->hashTable, &newEntry);
|
|
|
|
// check if mib entry found
|
|
fFoundOk = (newEntry != NULL);
|
|
|
|
// try mib tables
|
|
if (!fFoundOk) {
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: PDU: searching mib tables for %s.\n",
|
|
SnmpUtilOidToA(&hashOid)
|
|
));
|
|
|
|
// retrieve mib table information
|
|
numTables = extInfo->supportedView.viewTables.len;
|
|
viewTables = extInfo->supportedView.viewTables.list;
|
|
|
|
// scan mib tables for a match to the given oid
|
|
for (i=0; (i < numTables) && !fFoundOk; i++, viewTables++) {
|
|
|
|
// retrieve mib entry for table root
|
|
numItems = viewTables->tableItems.len;
|
|
newEntry = viewTables->tableItems.list;
|
|
|
|
if (!SnmpUtilOidNCmp(
|
|
&hashOid,
|
|
&newEntry->mibOid,
|
|
newEntry->mibOid.idLength)) {
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: PDU: 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: PDU: 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
|
|
fFoundOk = chkidx(
|
|
&indexOid,
|
|
&viewTables->tableIndex
|
|
);
|
|
|
|
// is index?
|
|
if (fFoundOk) {
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: PDU: saving index oid %s.\n",
|
|
SnmpUtilOidToA(&indexOid)
|
|
));
|
|
|
|
// allocate table translation structure
|
|
newXlat = (SnmpTableXlat *)SnmpUtilMemAlloc(
|
|
sizeof(SnmpTableXlat)
|
|
);
|
|
|
|
// save table information
|
|
newXlat->txInfo = viewTables;
|
|
newXlat->txIndex = i;
|
|
|
|
// copy index object identifier
|
|
SnmpUtilOidCpy(&newXlat->txOid, &indexOid);
|
|
|
|
break; // finished...
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
} else {
|
|
|
|
UINT newOff;
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: PDU: searching mib tables for %s.\n",
|
|
SnmpUtilOidToA(&hashOid)
|
|
));
|
|
|
|
// retrieve table information from supported view
|
|
numTables = extInfo->supportedView.viewTables.len;
|
|
viewTables = extInfo->supportedView.viewTables.list;
|
|
|
|
// scan mib tables for an entry in table
|
|
for (i=0; i < numTables; i++, viewTables++) {
|
|
|
|
// table entries are positioned after root
|
|
if (newEntry > viewTables->tableItems.list) {
|
|
|
|
// calculate the difference between pointers
|
|
newOff = (UINT)newEntry - (UINT)viewTables->tableItems.list;
|
|
|
|
// calculate table offset
|
|
newOff /= sizeof(SnmpMibEntry);
|
|
|
|
// determine whether entry within region
|
|
if (newOff <= viewTables->tableItems.len) {
|
|
|
|
// allocate table translation structure
|
|
newXlat = (SnmpTableXlat *)SnmpUtilMemAlloc(
|
|
sizeof(SnmpTableXlat)
|
|
);
|
|
|
|
// 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: PDU: mib entry is in table 0x%08lx (%s).\n",
|
|
viewTables->tableItems.list,
|
|
SnmpUtilOidToA(&viewTables->tableItems.list->mibOid)
|
|
));
|
|
|
|
break; // finished...
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// found entry?
|
|
if (fFoundOk) {
|
|
|
|
// pass back results
|
|
*mibEntry = newEntry;
|
|
*tblXlat = newXlat;
|
|
|
|
} else {
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: PDU: unable to exactly match varbind.\n"
|
|
));
|
|
|
|
// unable to locate varbind in mib table
|
|
*errorStatus = SNMP_ERRORSTATUS_NOSUCHNAME;
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
nextme(
|
|
RFC1157VarBind * vb,
|
|
SnmpMibEntry ** mibEntry,
|
|
UINT * mibAction,
|
|
SnmpTableXlat ** tblXlat,
|
|
UINT vlIndex,
|
|
UINT * errorStatus
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Locates next mib entry associated with given varbind.
|
|
|
|
Arguments:
|
|
|
|
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;
|
|
|
|
CfgExtAgents * extInfo = &extAgents[vl[vlIndex]];
|
|
|
|
// table?
|
|
if (*tblXlat) {
|
|
SNMPDBG((SNMP_LOG_VERBOSE, "SNMP: PDU: querying table.\n"));
|
|
return; // simply query table...
|
|
}
|
|
|
|
// retrieve entry
|
|
newEntry = *mibEntry;
|
|
|
|
// initialize
|
|
*mibEntry = NULL;
|
|
*tblXlat = NULL;
|
|
|
|
// continuing?
|
|
if (newEntry) {
|
|
// next
|
|
++newEntry;
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"SNMP: PDU: searching mib at next entry 0x%08lx.\n",
|
|
newEntry
|
|
));
|
|
} else {
|
|
// retrieve first mib entry in supported view
|
|
newEntry = extInfo->supportedView.viewScalars.list;
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"SNMP: PDU: searching mib at first entry 0x%08lx.\n",
|
|
newEntry
|
|
));
|
|
}
|
|
|
|
// initialize status to start search
|
|
mibStatus = SNMP_ERRORSTATUS_NOSUCHNAME;
|
|
|
|
// scan
|
|
for (;; newEntry++) {
|
|
|
|
// if last entry then we stop looking
|
|
if (newEntry->mibType == ASN_PRIVATE_EOM) {
|
|
|
|
SNMPDBG((SNMP_LOG_TRACE, "SNMP: PDU: 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
|
|
chkasn(&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: PDU: mib entry 0x%08lx found (%s).\n",
|
|
newEntry, SnmpUtilOidToA(&newEntry->mibOid)
|
|
));
|
|
|
|
// retrieve table information from supported view
|
|
numTables = extInfo->supportedView.viewTables.len;
|
|
viewTables = extInfo->supportedView.viewTables.list;
|
|
|
|
// scan mib tables for an entry in table
|
|
for (i=0; i < numTables; i++, viewTables++) {
|
|
|
|
// table entries are positioned after root
|
|
if (newEntry > viewTables->tableItems.list) {
|
|
|
|
// calculate the difference between pointers
|
|
newOff = (UINT)newEntry - (UINT)viewTables->tableItems.list;
|
|
|
|
// calculate table offset
|
|
newOff /= sizeof(SnmpMibEntry);
|
|
|
|
// determine whether entry within region
|
|
if (newOff <= viewTables->tableItems.len) {
|
|
|
|
// allocate table translation structure
|
|
newXlat = (SnmpTableXlat *)SnmpUtilMemAlloc(
|
|
sizeof(SnmpTableXlat)
|
|
);
|
|
|
|
// 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: PDU: mib entry is in table 0x%08lx (%s).\n",
|
|
viewTables->tableItems.list,
|
|
SnmpUtilOidToA(&viewTables->tableItems.list->mibOid)
|
|
));
|
|
|
|
break; // finished...
|
|
}
|
|
}
|
|
}
|
|
|
|
// 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: PDU: altered mib action to MIB_ACTION_GET.\n"
|
|
));
|
|
}
|
|
}
|
|
|
|
// pass back status
|
|
*errorStatus = mibStatus;
|
|
}
|
|
|
|
|
|
VOID
|
|
anyme(
|
|
RFC1157VarBind * vb,
|
|
SnmpMibEntry ** mibEntry,
|
|
UINT * mibAction,
|
|
SnmpTableXlat ** tblXlat,
|
|
UINT vlIndex,
|
|
UINT * errorStatus
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Locates any mib entry associated with given varbind.
|
|
|
|
Arguments:
|
|
|
|
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;
|
|
|
|
SnmpMibEntry * newEntry;
|
|
CfgExtAgents * extInfo = &extAgents[vl[vlIndex]];
|
|
|
|
// look for oid before view
|
|
fBefore = (0 > SnmpUtilOidNCmp(
|
|
&vb->name,
|
|
&extInfo->supportedView.viewOid,
|
|
extInfo->supportedView.viewOid.idLength
|
|
));
|
|
|
|
// look for exact match
|
|
fExact = !fBefore && !SnmpUtilOidCmp(
|
|
&vb->name,
|
|
&extInfo->supportedView.viewOid
|
|
);
|
|
|
|
// check for first...
|
|
if (!fBefore && !fExact) {
|
|
|
|
//
|
|
// CODEWORK - searching from random node in mib tree...
|
|
//
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"SNMP: PDU: random searching not yet implemented.\n"
|
|
));
|
|
|
|
*errorStatus = SNMP_ERRORSTATUS_GENERR;
|
|
|
|
} else {
|
|
|
|
// initialize
|
|
*mibEntry = NULL;
|
|
*tblXlat = NULL;
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"SNMP: PDU: searching %s for first entry.\n",
|
|
extAgents[vl[vlIndex]].extPath
|
|
));
|
|
|
|
// find next
|
|
nextme(vb,
|
|
mibEntry,
|
|
mibAction,
|
|
tblXlat,
|
|
vlIndex,
|
|
errorStatus
|
|
);
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
vbtome(
|
|
RFC1157VarBind * vb,
|
|
SnmpMibEntry ** mibEntry,
|
|
UINT * mibAction,
|
|
SnmpTableXlat ** tblXlat,
|
|
UINT vlIndex,
|
|
UINT * errorStatus
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Locates mib entry associated with given varbind.
|
|
|
|
Arguments:
|
|
|
|
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 exact match for variable binding
|
|
findme(vb, mibEntry, mibAction, tblXlat, vlIndex, errorStatus);
|
|
|
|
// get next?
|
|
if (fAnyOk) {
|
|
|
|
// search again
|
|
if (*errorStatus == SNMP_ERRORSTATUS_NOERROR) {
|
|
|
|
// find next entry in the supported view
|
|
nextme(vb, mibEntry, mibAction, tblXlat, vlIndex, errorStatus);
|
|
|
|
} else if (*errorStatus == SNMP_ERRORSTATUS_NOSUCHNAME) {
|
|
|
|
// find any entry in the supported view in proper order
|
|
anyme(vb, mibEntry, mibAction, tblXlat, vlIndex, errorStatus);
|
|
}
|
|
|
|
} else if (*errorStatus == SNMP_ERRORSTATUS_NOERROR) {
|
|
|
|
// validate asn value against mib entry information
|
|
chkasn(&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: PDU: 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;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
tbltoasn(
|
|
SnmpTableXlat * tblXlat,
|
|
AsnAny * objArray,
|
|
UINT mibAction
|
|
)
|
|
|
|
/*++
|
|
|
|
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 fEmpty;
|
|
|
|
UINT numItems;
|
|
|
|
SnmpMibEntry * mibEntry;
|
|
AsnObjectIdentifier * indexOid;
|
|
|
|
// retrieve root entry and entry count
|
|
numItems = tblXlat->txInfo->tableIndex.len;
|
|
mibEntry = tblXlat->txInfo->tableIndex.list;
|
|
|
|
// retrieve index oid
|
|
indexOid = &tblXlat->txOid;
|
|
|
|
// is this valid oid
|
|
fEmpty = (indexOid->idLength == 0);
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"SNMP: PDU: converting index %s to obj array via table 0x%08lx.\n",
|
|
fEmpty ? "<tbd>" : SnmpUtilOidToA(indexOid), mibEntry
|
|
));
|
|
|
|
// next
|
|
mibEntry++;
|
|
|
|
// scan mib entries of table indices
|
|
for (i=0, j=0; (i < numItems) && (j < indexOid->idLength); i++, mibEntry++) {
|
|
|
|
// retrieve array index
|
|
k = (mibAction == MIB_ACTION_SET)
|
|
? (UINT)(CHAR)mibEntry->mibSetBufOff
|
|
: (UINT)(CHAR)mibEntry->mibGetBufOff
|
|
;
|
|
|
|
// copy the type of asn variable
|
|
objArray[k].asnType = mibEntry->mibType;
|
|
|
|
// 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;
|
|
|
|
} else {
|
|
|
|
// variable length
|
|
l = indexOid->ids[j++];
|
|
}
|
|
|
|
// allocate object using length above
|
|
objArray[k].asnValue.object.idLength = l;
|
|
objArray[k].asnValue.object.ids = SnmpUtilMemAlloc(
|
|
objArray[k].asnValue.object.idLength * sizeof(UINT)
|
|
);
|
|
|
|
// transfer data
|
|
for (m=0; m < l; m++) {
|
|
|
|
// transfer oid element to buffer
|
|
objArray[k].asnValue.object.ids[m] = indexOid->ids[j++];
|
|
}
|
|
|
|
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;
|
|
|
|
} else {
|
|
|
|
// variable length
|
|
l = indexOid->ids[j++];
|
|
}
|
|
|
|
// 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)
|
|
);
|
|
|
|
// transfer data
|
|
for (m=0; m < l; m++) {
|
|
|
|
// convert oid element to character
|
|
objArray[k].asnValue.string.stream[m] =
|
|
(CHAR)indexOid->ids[j++];
|
|
}
|
|
|
|
break;
|
|
|
|
// implicit fixed size
|
|
case ASN_RFC1155_IPADDRESS:
|
|
|
|
// 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)
|
|
);
|
|
|
|
// transfer data into buffer
|
|
objArray[k].asnValue.string.stream[0] = (CHAR)indexOid->ids[j++];
|
|
objArray[k].asnValue.string.stream[1] = (CHAR)indexOid->ids[j++];
|
|
objArray[k].asnValue.string.stream[2] = (CHAR)indexOid->ids[j++];
|
|
objArray[k].asnValue.string.stream[3] = (CHAR)indexOid->ids[j++];
|
|
|
|
break;
|
|
|
|
case ASN_RFC1155_COUNTER:
|
|
case ASN_RFC1155_GAUGE:
|
|
case ASN_RFC1155_TIMETICKS:
|
|
case ASN_INTEGER:
|
|
|
|
// transfer value as integer
|
|
objArray[k].asnValue.number = indexOid->ids[j++];
|
|
break;
|
|
|
|
default:
|
|
// invalidate
|
|
j = INVALID_INDEX;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
isindex(
|
|
SnmpMibEntry * mibEntry,
|
|
SnmpTableXlat * tblXlat
|
|
)
|
|
{
|
|
UINT newOff;
|
|
BOOL fFoundOk = FALSE;
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: PDU: comparing mibEntry 0x%08lx to tableEntry 0x%08lx.\n",
|
|
mibEntry,
|
|
tblXlat->txInfo->tableIndex.list
|
|
));
|
|
|
|
// make sure mib entry pointer greater than table
|
|
if (mibEntry > tblXlat->txInfo->tableIndex.list) {
|
|
|
|
// calculate the difference between pointers
|
|
newOff = (UINT)mibEntry - (UINT)tblXlat->txInfo->tableIndex.list;
|
|
|
|
// calculate table offset
|
|
newOff /= sizeof(SnmpMibEntry);
|
|
|
|
// determine whether entry within region
|
|
fFoundOk = (newOff <= tblXlat->txInfo->tableIndex.len);
|
|
}
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: PDU: mibEntry %s a component of the table's index (offset=%d, len=%d).\n",
|
|
fFoundOk ? "is" : "is not",
|
|
newOff,
|
|
tblXlat->txInfo->tableIndex.len
|
|
));
|
|
|
|
return fFoundOk;
|
|
}
|
|
|
|
|
|
VOID
|
|
metoql(
|
|
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;
|
|
|
|
BOOL fFoundOk = FALSE;
|
|
|
|
CfgExtAgents * extInfo = &extAgents[vl[vlIndex]];
|
|
|
|
// retrieve type of supported view
|
|
viewType = extInfo->supportedView.viewType;
|
|
|
|
// determine instrumentation callback
|
|
extFunc = (viewType == MIB_VIEW_OPAQUE)
|
|
? extInfo->queryFunc
|
|
: (mibAction == MIB_ACTION_SET)
|
|
? mibEntry->mibSetFunc
|
|
: mibEntry->mibGetFunc
|
|
;
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"SNMP: PDU: processing query for %s (%s).\n",
|
|
extInfo->extPath,
|
|
(viewType == MIB_VIEW_OPAQUE)
|
|
? "opaque"
|
|
: "normal"
|
|
));
|
|
|
|
// 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->viewType == viewType) &&
|
|
(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
|
|
ql->query = (SnmpExtQuery *)SnmpUtilMemReAlloc(
|
|
ql->query,
|
|
ql->len * sizeof(SnmpExtQuery)
|
|
);
|
|
|
|
// retrieve new query pointer
|
|
extQuery = &ql->query[ql->len-1];
|
|
|
|
// save common information
|
|
extQuery->mibAction = mibAction;
|
|
extQuery->viewType = viewType;
|
|
extQuery->extFunc = extFunc;
|
|
|
|
// initialize list
|
|
extQuery->vblNum = 0;
|
|
extQuery->vblXlat = NULL;
|
|
|
|
// view specific initialization
|
|
if (viewType == MIB_VIEW_NORMAL) {
|
|
|
|
// 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);
|
|
|
|
// initialize asn array
|
|
tbltoasn(tblXlat, objArray, mibAction);
|
|
|
|
// save table info
|
|
extQuery->tblXlat = tblXlat;
|
|
}
|
|
|
|
} else {
|
|
|
|
// free table oid
|
|
SnmpUtilOidFree(&tblXlat->txOid);
|
|
|
|
// free table info
|
|
SnmpUtilMemFree(tblXlat);
|
|
|
|
// report memory allocation problem
|
|
*errorStatus = SNMP_ERRORSTATUS_GENERR;
|
|
return; // bail...
|
|
}
|
|
|
|
} else {
|
|
|
|
// no table info
|
|
extQuery->tblXlat = NULL;
|
|
|
|
// initialize list
|
|
extQuery->extData.len = 0;
|
|
extQuery->extData.data = NULL;
|
|
}
|
|
|
|
}
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"SNMP: PDU: %s query 0x%08lx (%s).\n",
|
|
fFoundOk ? "editing" : "adding",
|
|
extQuery,
|
|
extAgents[vl[vlIndex]].extPath
|
|
));
|
|
|
|
// copy to index
|
|
i = extQuery->vblNum;
|
|
|
|
// allocate entry
|
|
extQuery->vblNum++;
|
|
extQuery->vblXlat = (SnmpVarBindXlat *)SnmpUtilMemReAlloc(
|
|
extQuery->vblXlat,
|
|
extQuery->vblNum * sizeof(SnmpVarBindXlat)
|
|
);
|
|
|
|
// copy common xlate information
|
|
extQuery->vblXlat[i].vblIndex = vb;
|
|
extQuery->vblXlat[i].vlIndex = vlIndex;
|
|
extQuery->vblXlat[i].extQuery = NULL;
|
|
|
|
// other info depends on type
|
|
if (viewType == MIB_VIEW_NORMAL) {
|
|
|
|
// 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 asn type
|
|
if (!objArray[i].asnType) {
|
|
|
|
// ignore table index values
|
|
if (tblXlat && isindex(mibEntry,tblXlat)) {
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: PDU: requesting index value.\n"
|
|
));
|
|
|
|
} else {
|
|
|
|
// initialize asn type to match entry
|
|
objArray[i].asnType = mibEntry->mibType;
|
|
}
|
|
|
|
} else if (mibAction == MIB_ACTION_SET) {
|
|
|
|
// copy user-supplied value into buffer
|
|
SnmpUtilAsnAnyCpy(&objArray[i], &vbl->list[vb].value);
|
|
}
|
|
|
|
} else {
|
|
|
|
RFC1157VarBind * tmpVbl;
|
|
|
|
// save translation info
|
|
extQuery->vblXlat[i].mibEntry = NULL;
|
|
|
|
// copy to index
|
|
j = extQuery->extData.len;
|
|
|
|
// allocate varbind
|
|
extQuery->extData.len++;
|
|
extQuery->extData.data = SnmpUtilMemReAlloc(
|
|
extQuery->extData.data,
|
|
extQuery->extData.len * sizeof(RFC1157VarBind)
|
|
);
|
|
|
|
// retrieve pointer to varbind list
|
|
tmpVbl = (RFC1157VarBind *)(extQuery->extData.data);
|
|
|
|
// copy varbind
|
|
SnmpUtilVarBindCpy(
|
|
&tmpVbl[j],
|
|
&vbl->list[vb]
|
|
);
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
vbtoql(
|
|
RFC1157VarBindList * vbl,
|
|
SnmpExtQueryList * ql,
|
|
UINT vb,
|
|
UINT * errorStatus,
|
|
UINT queryView
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Adds varbind to query list.
|
|
|
|
Arguments:
|
|
|
|
vbl - list of varbinds.
|
|
ql - list of subagent queries.
|
|
vb - index of varbind to add to query.
|
|
errorStatus - used to indicate success or failure.
|
|
queryView - view of query requested.
|
|
|
|
Return Values:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
INT i;
|
|
INT nDiff;
|
|
|
|
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: PDU: searching subagents to resolve %s.\n",
|
|
SnmpUtilOidToA(&vbl->list[vb].name)
|
|
));
|
|
|
|
// locate appropriate view (starting at queryView)
|
|
for (i = queryView; (i < (INT)vlLen) && !fFoundOk; i++) {
|
|
|
|
// retrieve the mib view information
|
|
mibView = &extAgents[vl[i]].supportedView;
|
|
|
|
// 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)));
|
|
|
|
// 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;
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"SNMP: PDU: searching %s for mib entry.\n",
|
|
extAgents[vl[i]].extPath
|
|
));
|
|
|
|
// load mib entry
|
|
vbtome(&vbl->list[vb],
|
|
&mibEntry,
|
|
&mibAction,
|
|
&tblXlat,
|
|
i,
|
|
&mibStatus
|
|
);
|
|
|
|
// successfully loaded mib entry information
|
|
fFoundOk = (mibStatus == SNMP_ERRORSTATUS_NOERROR);
|
|
|
|
// ignore no such name error since we are searching
|
|
if (!fFoundOk && (mibStatus != SNMP_ERRORSTATUS_NOSUCHNAME)) {
|
|
// pass up error status
|
|
*errorStatus = mibStatus;
|
|
return; // bail...
|
|
}
|
|
}
|
|
}
|
|
|
|
// found?
|
|
if (fFoundOk) {
|
|
// save query
|
|
metoql(mibEntry,
|
|
mibAction,
|
|
ql,
|
|
tblXlat,
|
|
i-1,
|
|
vbl,
|
|
vb,
|
|
errorStatus
|
|
);
|
|
} else {
|
|
// variable not supported in any subagent
|
|
*errorStatus = SNMP_ERRORSTATUS_NOSUCHNAME;
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
vbltoql(
|
|
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:
|
|
|
|
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: PDU: 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) && !(*errorStatus); i++) {
|
|
|
|
// place varbind in query
|
|
vbtoql(vbl, ql, i, errorStatus, 0);
|
|
}
|
|
|
|
// make sure we report the errant variable
|
|
if (*errorStatus != SNMP_ERRORSTATUS_NOERROR) {
|
|
*errorIndex = i;
|
|
}
|
|
}
|
|
|
|
|
|
UINT
|
|
mkerr(
|
|
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
|
|
fixuperr(
|
|
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;
|
|
|
|
// ignore zero
|
|
if (errorIndexOld) {
|
|
|
|
// make sure within bounds
|
|
if (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
|
|
doq(
|
|
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;
|
|
|
|
// determine type of instrumentation
|
|
if (q->viewType == MIB_VIEW_NORMAL) {
|
|
|
|
AsnAny * objArray;
|
|
|
|
// retrieve asn object array
|
|
objArray = (AsnAny *)(q->extData.data);
|
|
|
|
__try {
|
|
|
|
// query subagent
|
|
extStatus = (*q->extFunc)(
|
|
q->mibAction,
|
|
objArray,
|
|
errorIndex
|
|
);
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"SNMP: PDU: subagent returned %s (0x%08lx).\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
|
|
));
|
|
|
|
} __except (EXCEPTION_EXECUTE_HANDLER) {
|
|
|
|
// report exception code
|
|
extStatus = GetExceptionCode();
|
|
|
|
// disable
|
|
fOk = FALSE;
|
|
}
|
|
|
|
// save error info
|
|
SetLastError(extStatus);
|
|
|
|
// pass back translated version
|
|
*errorStatus = mkerr(extStatus);
|
|
|
|
} else {
|
|
|
|
RFC1157VarBindList * vbl;
|
|
|
|
// retrieve varbind from extension data
|
|
vbl = (RFC1157VarBindList *)(&q->extData);
|
|
|
|
__try {
|
|
|
|
// query subagent
|
|
fOk = (*q->extFunc)(
|
|
q->mibAction,
|
|
vbl,
|
|
errorStatus,
|
|
errorIndex
|
|
);
|
|
|
|
} __except(EXCEPTION_EXECUTE_HANDLER) {
|
|
|
|
// report exception code
|
|
extStatus = GetExceptionCode();
|
|
|
|
// disable
|
|
fOk = FALSE;
|
|
}
|
|
}
|
|
|
|
if (!fOk) {
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"SNMP: PDU: subagent failed request (0x%08lx).\n",
|
|
extStatus
|
|
));
|
|
}
|
|
|
|
return fOk;
|
|
}
|
|
|
|
|
|
VOID
|
|
doql(
|
|
SnmpExtQueryList * ql,
|
|
UINT * errorStatus,
|
|
UINT * errorIndex
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Process the query list based on request type.
|
|
|
|
Arguments:
|
|
|
|
ql - list of subagent queries.
|
|
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: PDU: 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 (doq(&ql->query[i], errorStatus, errorIndex)) {
|
|
|
|
// need to validate getnext results
|
|
if (ql->action == MIB_ACTION_GETNEXT) {
|
|
// exhaust all possibilities...
|
|
chkql(ql, i, errorStatus, errorIndex);
|
|
}
|
|
|
|
// check the subagent status code returned
|
|
if (*errorStatus != SNMP_ERRORSTATUS_NOERROR) {
|
|
// adjust index to match request pdu
|
|
fixuperr(&ql->query[i], errorIndex);
|
|
}
|
|
|
|
} else {
|
|
|
|
// subagent unable to process query
|
|
*errorStatus = SNMP_ERRORSTATUS_GENERR;
|
|
*errorIndex = 1;
|
|
// adjust index to match request pdu
|
|
fixuperr(&ql->query[i], errorIndex);
|
|
}
|
|
}
|
|
|
|
} else {
|
|
|
|
// process all of the validate queries
|
|
for (i=0; (i < qlLen) && !(*errorStatus); i++) {
|
|
|
|
// only query the updated subagents
|
|
if (ql->query[i].viewType == MIB_VIEW_NORMAL) {
|
|
|
|
// alter query type to validate entries
|
|
ql->query[i].mibAction = MIB_ACTION_VALIDATE;
|
|
|
|
// send query to subagent
|
|
if (doq(&ql->query[i], errorStatus, errorIndex)) {
|
|
|
|
// check the subagent status code returned
|
|
if (*errorStatus != SNMP_ERRORSTATUS_NOERROR) {
|
|
// adjust index to match request pdu
|
|
fixuperr(&ql->query[i], errorIndex);
|
|
}
|
|
|
|
} else {
|
|
|
|
// subagent unable to process query
|
|
*errorStatus = SNMP_ERRORSTATUS_GENERR;
|
|
*errorIndex = 1;
|
|
// adjust index to match request pdu
|
|
fixuperr(&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 (doq(&ql->query[j], errorStatus, errorIndex)) {
|
|
|
|
// check the subagent status code returned
|
|
if (*errorStatus != SNMP_ERRORSTATUS_NOERROR) {
|
|
// adjust index to match request pdu
|
|
fixuperr(&ql->query[j], errorIndex);
|
|
}
|
|
|
|
} else {
|
|
|
|
// subagent unable to process query
|
|
*errorStatus = SNMP_ERRORSTATUS_GENERR;
|
|
*errorIndex = 1;
|
|
// adjust index to match request pdu
|
|
fixuperr(&ql->query[j], errorIndex);
|
|
}
|
|
}
|
|
|
|
// cleanup...
|
|
while (i-- > 0) {
|
|
|
|
// only query the updated subagents
|
|
if (ql->query[i].viewType == MIB_VIEW_NORMAL) {
|
|
|
|
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
|
|
doq(&ql->query[j], &ignoreStatus, &ignoreIndex);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
metooid(
|
|
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:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
UINT i;
|
|
UINT j;
|
|
UINT k;
|
|
UINT l;
|
|
UINT m;
|
|
|
|
BOOL fFixed;
|
|
BOOL fLimit;
|
|
|
|
UINT numItems;
|
|
|
|
SnmpMibEntry * mibEntry;
|
|
|
|
// initialize
|
|
newOid->ids = NULL;
|
|
newOid->idLength = 0;
|
|
|
|
// retrieve root entry and entry count
|
|
numItems = tblXlat->txInfo->tableIndex.len;
|
|
mibEntry = tblXlat->txInfo->tableIndex.list;
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"SNMP: PDU: converting obj array to index via table 0x%08lx.\n",
|
|
mibEntry
|
|
));
|
|
|
|
// next
|
|
mibEntry++;
|
|
|
|
// scan mib entries of table indices ensuring match of given oid
|
|
for (i=0, j=0; i < numItems; i++, mibEntry++) {
|
|
|
|
// 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
|
|
l = mibEntry->mibMaximum;
|
|
|
|
// allocate space
|
|
newOid->idLength += l;
|
|
newOid->ids = (UINT *)SnmpUtilMemReAlloc(
|
|
newOid->ids,
|
|
newOid->idLength * sizeof(UINT)
|
|
);
|
|
|
|
} else {
|
|
|
|
// determine variable length of object
|
|
l = objArray[k].asnValue.object.idLength;
|
|
|
|
// allocate space
|
|
newOid->idLength += (l+1);
|
|
newOid->ids = (UINT *)SnmpUtilMemReAlloc(
|
|
newOid->ids,
|
|
newOid->idLength * sizeof(UINT)
|
|
);
|
|
|
|
// 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;
|
|
newOid->ids = (UINT *)SnmpUtilMemReAlloc(
|
|
newOid->ids,
|
|
newOid->idLength * sizeof(UINT)
|
|
);
|
|
|
|
} else {
|
|
|
|
// determine variable length of object
|
|
l = objArray[k].asnValue.string.length;
|
|
|
|
// allocate space
|
|
newOid->idLength += (l+1);
|
|
newOid->ids = (UINT *)SnmpUtilMemReAlloc(
|
|
newOid->ids,
|
|
newOid->idLength * sizeof(UINT)
|
|
);
|
|
|
|
// save length
|
|
newOid->ids[j++] = l;
|
|
}
|
|
|
|
// transfer data
|
|
for (m=0; m < l; m++) {
|
|
|
|
// convert character
|
|
newOid->ids[j++] =
|
|
(UINT)(CHAR)objArray[k].asnValue.string.stream[m];
|
|
}
|
|
|
|
break;
|
|
|
|
// implicit fixed size
|
|
case ASN_RFC1155_IPADDRESS:
|
|
|
|
// allocate space
|
|
newOid->idLength += 4;
|
|
newOid->ids = (UINT *)SnmpUtilMemReAlloc(
|
|
newOid->ids,
|
|
newOid->idLength * sizeof(UINT)
|
|
);
|
|
|
|
// transfer data into buffer
|
|
newOid->ids[j++] = (UINT)(CHAR)objArray[k].asnValue.string.stream[0];
|
|
newOid->ids[j++] = (UINT)(CHAR)objArray[k].asnValue.string.stream[1];
|
|
newOid->ids[j++] = (UINT)(CHAR)objArray[k].asnValue.string.stream[2];
|
|
newOid->ids[j++] = (UINT)(CHAR)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;
|
|
newOid->ids = (UINT *)SnmpUtilMemReAlloc(
|
|
newOid->ids,
|
|
newOid->idLength * sizeof(UINT)
|
|
);
|
|
|
|
// transfer value as integer
|
|
newOid->ids[j++] = objArray[k].asnValue.number;
|
|
break;
|
|
|
|
default:
|
|
// invalidate
|
|
j = INVALID_INDEX;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
delq(
|
|
SnmpExtQuery * q
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Deletes individual query.
|
|
|
|
Arguments:
|
|
|
|
q - subagent query.
|
|
|
|
Return Values:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: PDU: deleting query 0x%08lx.\n", q
|
|
));
|
|
|
|
if (q->viewType == MIB_VIEW_NORMAL) {
|
|
|
|
UINT i; // index into xlat array
|
|
UINT j; // index into object array
|
|
|
|
BOOL fSet;
|
|
|
|
AsnAny * objArray;
|
|
SnmpMibEntry * mibEntry;
|
|
|
|
// 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;
|
|
|
|
j = fSet ? (UINT)(CHAR)mibEntry->mibSetBufOff
|
|
: (UINT)(CHAR)mibEntry->mibGetBufOff
|
|
;
|
|
|
|
SnmpUtilAsnAnyFree(&objArray[j]);
|
|
|
|
// free any followup queries
|
|
if (q->vblXlat[i].extQuery) {
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: PDU: deleting followup query 0x%08lx.\n",
|
|
q->vblXlat[i].extQuery
|
|
));
|
|
|
|
// free followup query
|
|
delq(q->vblXlat[i].extQuery);
|
|
|
|
// free query structure itself
|
|
SnmpUtilMemFree(q->vblXlat[i].extQuery);
|
|
}
|
|
}
|
|
|
|
// free indices
|
|
if (q->tblXlat) {
|
|
|
|
// point to first index mib entry
|
|
mibEntry = q->tblXlat->txInfo->tableIndex.list;
|
|
|
|
// free the individual indices
|
|
for (i = 0; i < q->tblXlat->txInfo->tableIndex.len; i++, 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);
|
|
|
|
// free table info
|
|
if (q->tblXlat) {
|
|
|
|
// free object identifier
|
|
SnmpUtilOidFree(&q->tblXlat->txOid);
|
|
|
|
// free the xlat structure
|
|
SnmpUtilMemFree(q->tblXlat);
|
|
}
|
|
|
|
} else {
|
|
|
|
RFC1157VarBindList * vbl;
|
|
|
|
// use extension data as varbind list
|
|
vbl = (RFC1157VarBindList *)(&q->extData);
|
|
|
|
// free varbind list
|
|
SnmpUtilVarBindListFree(vbl);
|
|
}
|
|
|
|
// free translation info
|
|
SnmpUtilMemFree(q->vblXlat);
|
|
}
|
|
|
|
|
|
VOID
|
|
delql(
|
|
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
|
|
delq(&ql->query[q]);
|
|
}
|
|
|
|
// free query list
|
|
SnmpUtilMemFree(ql->query);
|
|
}
|
|
|
|
|
|
VOID
|
|
qtovbl(
|
|
SnmpExtQuery * q,
|
|
RFC1157VarBindList * vbl
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Convert query back into varbind.
|
|
|
|
Arguments:
|
|
|
|
q - subagent query.
|
|
vbl - list of varbinds in outgoing pdu.
|
|
|
|
Return Values:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
UINT i;
|
|
UINT j;
|
|
UINT k;
|
|
UINT l;
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: PDU: converting query 0x%08lx to varbinds.\n", q
|
|
));
|
|
|
|
// convert the mib information
|
|
if (q->viewType == MIB_VIEW_NORMAL) {
|
|
|
|
BOOL fSet;
|
|
|
|
AsnAny * objArray;
|
|
SnmpMibEntry * mibEntry;
|
|
|
|
AsnObjectIdentifier idxOid;
|
|
|
|
// 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) {
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: PDU: processing followup query 0x%08lx.\n",
|
|
q->vblXlat[j].extQuery
|
|
));
|
|
|
|
qtovbl(q->vblXlat[j].extQuery, vbl);
|
|
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
|
|
SnmpUtilAsnAnyCpy(&vbl->list[i].value, &objArray[k]);
|
|
|
|
// copy root oid of view
|
|
SnmpUtilOidCpy(
|
|
&vbl->list[i].name,
|
|
&extAgents[vl[q->vblXlat[j].vlIndex]].supportedView.viewOid
|
|
);
|
|
|
|
// copy oid of variable
|
|
SnmpUtilOidAppend(
|
|
&vbl->list[i].name,
|
|
&mibEntry->mibOid
|
|
);
|
|
|
|
// copy table index
|
|
if (q->tblXlat) {
|
|
|
|
// convert value to oid
|
|
metooid(q->tblXlat, objArray, &idxOid, q->mibAction);
|
|
|
|
// append oid to object name
|
|
SnmpUtilOidAppend(&vbl->list[i].name, &idxOid);
|
|
|
|
// free temp oid
|
|
SnmpUtilOidFree(&idxOid);
|
|
}
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"SNMP: PDU: returning oid %s.\n",
|
|
SnmpUtilOidToA(&vbl->list[i].name)
|
|
));
|
|
}
|
|
|
|
} else {
|
|
|
|
RFC1157VarBind * vb;
|
|
|
|
// process varbinds gathered
|
|
for (j = 0; j < q->vblNum; j++) {
|
|
|
|
// calculate original index
|
|
i = q->vblXlat[j].vblIndex;
|
|
|
|
// free original variable
|
|
SnmpUtilVarBindFree(&vbl->list[i]);
|
|
|
|
// retrieve pointer to varbind list
|
|
vb = (RFC1157VarBind *)(q->extData.data);
|
|
|
|
// copy new variable to original buffer
|
|
SnmpUtilVarBindCpy(&vbl->list[i], &vb[j]);
|
|
|
|
// free original variable
|
|
SnmpUtilVarBindFree(&vb[j]);
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"SNMP: PDU: returning oid %s.\n",
|
|
SnmpUtilOidToA(&vbl->list[i].name)
|
|
));
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
qltovbl(
|
|
SnmpExtQueryList * ql,
|
|
RFC1157VarBindList * vbl,
|
|
UINT * errorStatus,
|
|
UINT * errorIndex
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Convert query list back into outgoing varbinds.
|
|
|
|
Arguments:
|
|
|
|
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: PDU: 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
|
|
qtovbl(&ql->query[q], vbl);
|
|
}
|
|
}
|
|
|
|
// free
|
|
delql(ql);
|
|
}
|
|
|
|
|
|
VOID
|
|
chkql(
|
|
SnmpExtQueryList * ql,
|
|
UINT q,
|
|
UINT * errorStatus,
|
|
UINT * errorIndex
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Validate getnext results and re-query if necessary.
|
|
|
|
Arguments:
|
|
|
|
ql - list of subagent queries.
|
|
q - subagent query of interest.
|
|
errorStatus - used to indicate success or failure.
|
|
errorIndex - used to identify an errant varbind.
|
|
|
|
Return Values:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
UINT i;
|
|
UINT j;
|
|
|
|
SnmpExtQueryList tmpQl;
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"SNMP: PDU: verifying results of query 0x%08lx.\n", &ql->query[q]
|
|
));
|
|
|
|
// determine type of query we are processing
|
|
if (ql->query[q].viewType == MIB_VIEW_NORMAL) {
|
|
|
|
UINT vlIndex;
|
|
UINT mibAction;
|
|
UINT mibStatus;
|
|
SnmpMibEntry * mibEntry;
|
|
SnmpTableXlat * tblXlat;
|
|
RFC1157VarBindList tmpVbl;
|
|
BOOL fFoundOk = FALSE;
|
|
|
|
// bail on any error other than no such name
|
|
if (*errorStatus != SNMP_ERRORSTATUS_NOSUCHNAME) {
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"SNMP: PDU: returning error %d.\n",
|
|
GetLastError()
|
|
));
|
|
|
|
return; // bail...
|
|
}
|
|
|
|
// scan query list updating variables
|
|
for (i=0; i < ql->query[q].vblNum; i++) {
|
|
|
|
// initialize
|
|
vlIndex = ql->query[q].vblXlat[i].vlIndex;
|
|
mibEntry = ql->query[q].vblXlat[i].mibEntry;
|
|
|
|
tblXlat = NULL;
|
|
mibAction = MIB_ACTION_GETNEXT;
|
|
|
|
// retrieve view index
|
|
j = ql->query[q].vblXlat[i].vlIndex;
|
|
|
|
// next...
|
|
nextme(NULL,
|
|
&mibEntry,
|
|
&mibAction,
|
|
&tblXlat,
|
|
vlIndex,
|
|
errorStatus
|
|
);
|
|
|
|
while (*errorStatus == SNMP_ERRORSTATUS_NOERROR) {
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"SNMP: PDU: constructing followup to query 0x%08lx:\n"
|
|
"SNMP: PDU: \tmibEntry=0x%08lx\n"
|
|
"SNMP: PDU: \ttblXlat =0x%08lx\n",
|
|
&ql->query[q],
|
|
mibEntry,
|
|
tblXlat
|
|
));
|
|
|
|
// initialize
|
|
tmpQl.len = 0;
|
|
tmpQl.query = NULL;
|
|
tmpQl.action = MIB_ACTION_GETNEXT;
|
|
|
|
// create query
|
|
metoql(mibEntry,
|
|
mibAction,
|
|
&tmpQl,
|
|
tblXlat,
|
|
vlIndex,
|
|
NULL,
|
|
ql->query[q].vblXlat[i].vblIndex,
|
|
errorStatus
|
|
);
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"SNMP: PDU: processing followup query 0x%08lx.\n",
|
|
tmpQl.query
|
|
));
|
|
|
|
// perform query with new oid
|
|
doq(tmpQl.query, errorStatus, errorIndex);
|
|
|
|
// calculate results of query
|
|
if (*errorStatus == SNMP_ERRORSTATUS_NOERROR) {
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"SNMP: PDU: 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: PDU: re-processing followup to query 0x%08lx.\n",
|
|
&ql->query[q]
|
|
));
|
|
|
|
// re-initialize and continue...
|
|
*errorStatus = SNMP_ERRORSTATUS_NOERROR;
|
|
|
|
// delete...
|
|
delql(&tmpQl);
|
|
|
|
} else {
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"SNMP: PDU: could not process followup.\n"
|
|
));
|
|
|
|
// delete...
|
|
delql(&tmpQl);
|
|
|
|
return; // bail...
|
|
}
|
|
|
|
// initialize
|
|
tblXlat = NULL;
|
|
mibAction = MIB_ACTION_GETNEXT;
|
|
|
|
// next...
|
|
nextme(NULL,
|
|
&mibEntry,
|
|
&mibAction,
|
|
&tblXlat,
|
|
vlIndex,
|
|
errorStatus
|
|
);
|
|
}
|
|
|
|
// attempt to query next supported subagent view
|
|
if (*errorStatus == SNMP_ERRORSTATUS_NOSUCHNAME) {
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"SNMP: PDU: re-processing followup to query 0x%08lx (again).\n",
|
|
&ql->query[q]
|
|
));
|
|
|
|
// initialize
|
|
tmpQl.len = 0;
|
|
tmpQl.query = NULL;
|
|
tmpQl.action = MIB_ACTION_GETNEXT;
|
|
|
|
// allocate varbind
|
|
tmpVbl.len = 1;
|
|
tmpVbl.list = (RFC1157VarBind *)SnmpUtilMemAlloc(
|
|
sizeof(RFC1157VarBind)
|
|
);
|
|
|
|
// copy varbind
|
|
SnmpUtilOidCpy(
|
|
&tmpVbl.list->name,
|
|
&extAgents[vl[j]].supportedView.viewOid
|
|
);
|
|
|
|
// increment last element of view oid
|
|
tmpVbl.list->name.ids[tmpVbl.list->name.idLength-1]++;
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_VERBOSE,
|
|
"SNMP: PDU: changing varbind to %s.\n",
|
|
SnmpUtilOidToA(&tmpVbl.list[0].name)
|
|
));
|
|
|
|
// we need to query again with new oid
|
|
vbtoql(&tmpVbl, &tmpQl, 0, errorStatus, j+1);
|
|
|
|
// make sure we successfully processed query
|
|
if (*errorStatus == SNMP_ERRORSTATUS_NOERROR) {
|
|
|
|
// perform query with new oid
|
|
doq(tmpQl.query, errorStatus, errorIndex);
|
|
|
|
// make sure we successfully processed query
|
|
if (*errorStatus == SNMP_ERRORSTATUS_NOERROR) {
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"SNMP: PDU: 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...
|
|
}
|
|
}
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"SNMP: PDU: could not process followup (again).\n"
|
|
));
|
|
|
|
// delete...
|
|
delql(&tmpQl);
|
|
|
|
return; // bail...
|
|
}
|
|
}
|
|
|
|
} else {
|
|
|
|
RFC1157VarBindList * tmpVbl;
|
|
|
|
// retrieve varbind list
|
|
tmpVbl = (RFC1157VarBindList *)(&ql->query[q].extData);
|
|
|
|
// scan varbind list verifying oids in view
|
|
for (i=0; (i < ql->query[q].vblNum) && !(*errorStatus); i++) {
|
|
|
|
// retrieve view index
|
|
j = ql->query[q].vblXlat->vlIndex;
|
|
|
|
// was this serviced?
|
|
if (0 < SnmpUtilOidNCmp(
|
|
&tmpVbl->list[i].name,
|
|
&extAgents[vl[j]].supportedView.viewOid,
|
|
extAgents[vl[j]].supportedView.viewOid.idLength
|
|
)) {
|
|
|
|
SNMPDBG((
|
|
SNMP_LOG_TRACE,
|
|
"SNMP: PDU: processing followup to query 0x%08lx.\n", q
|
|
));
|
|
|
|
// initialize
|
|
tmpQl.len = 0;
|
|
tmpQl.query = NULL;
|
|
tmpQl.action = MIB_ACTION_GETNEXT;
|
|
|
|
// we need to query again with new oid
|
|
vbtoql(tmpVbl, &tmpQl, i, errorStatus, j+1);
|
|
|
|
// perform query with new oid
|
|
doql(&tmpQl, errorStatus, errorIndex);
|
|
|
|
// recover new results from additional query
|
|
qltovbl(&tmpQl, tmpVbl, errorStatus, errorIndex);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//--------------------------- PUBLIC PROCEDURES -----------------------------
|
|
|
|
SNMPAPI SnmpServiceProcessMessage(
|
|
IN OUT BYTE **pBuf,
|
|
IN OUT UINT *length)
|
|
{
|
|
static BOOL fInitedOk = FALSE;
|
|
|
|
RFC1157VarBindList vbl;
|
|
SnmpExtQueryList ql;
|
|
SnmpMgmtCom request;
|
|
|
|
AsnInteger errorStatus;
|
|
AsnInteger errorIndex;
|
|
|
|
BOOL fEncodedOk;
|
|
|
|
UINT packetType;
|
|
UINT q;
|
|
|
|
// init views
|
|
if (!fInitedOk)
|
|
{
|
|
initvl();
|
|
fInitedOk = TRUE;
|
|
}
|
|
|
|
// decode received request into a management comm
|
|
if (!SnmpSvcDecodeMessage(&packetType, &request, *pBuf, *length, TRUE))
|
|
return FALSE;
|
|
|
|
// initialize variables
|
|
vbl = request.pdu.pduValue.pdu.varBinds;
|
|
|
|
ql.query = NULL;
|
|
ql.len = 0;
|
|
ql.action = request.pdu.pduType;
|
|
|
|
// disassemble varbinds into queries
|
|
vbltoql(&vbl, &ql, &errorStatus, &errorIndex);
|
|
|
|
// process queries based on request
|
|
doql(&ql, &errorStatus, &errorIndex);
|
|
|
|
// reassemble queries into response varbinds
|
|
qltovbl(&ql, &vbl, &errorStatus, &errorIndex);
|
|
|
|
// construct reponse pdu with varbinds
|
|
request.pdu.pduType = ASN_RFC1157_GETRESPONSE;
|
|
|
|
request.pdu.pduValue.pdu.errorStatus = errorStatus;
|
|
request.pdu.pduValue.pdu.errorIndex = errorIndex;
|
|
|
|
request.pdu.pduValue.pdu.varBinds = vbl;
|
|
|
|
*pBuf = NULL;
|
|
*length = 0;
|
|
|
|
// encode response pdu with gathered varbinds
|
|
fEncodedOk = SnmpSvcEncodeMessage(packetType, &request, pBuf, length);
|
|
|
|
// release response message
|
|
SnmpSvcReleaseMessage(&request);
|
|
|
|
return fEncodedOk;
|
|
|
|
} // end SnmpServiceProcessMessage()
|
|
|
|
// filter managers with permitted managers in registry
|
|
BOOL filtmgrs(struct sockaddr *source, INT sourceLen)
|
|
{
|
|
BOOL fFound = FALSE;
|
|
INT i;
|
|
|
|
if (permitMgrsLen > 0)
|
|
{
|
|
for(i=0; i < permitMgrsLen && !fFound; i++)
|
|
{
|
|
DWORD test;
|
|
SOCKADDR_IPX * pIpx;
|
|
// --------- BEGIN: PROTOCOL SPECIFIC SOCKET CODE BEGIN... ---------
|
|
switch (source->sa_family)
|
|
{
|
|
case AF_INET:
|
|
if ((*((struct sockaddr_in *)source)).sin_addr.s_addr ==
|
|
(*((struct sockaddr_in *)&permitMgrs[i].addrEncoding)).sin_addr.s_addr)
|
|
{
|
|
fFound = TRUE;
|
|
}
|
|
break;
|
|
|
|
case AF_IPX:
|
|
|
|
#ifdef debug
|
|
dp_ipx(SNMP_LOG_TRACE, "SNMP: PDU: validating IPX manager @ ",
|
|
(SOCKADDR_IPX *) source, " against ");
|
|
SNMPDBG((SNMP_LOG_TRACE, "(%04X)", permitMgrs[i].addrEncoding.sa_family));
|
|
dp_ipx(SNMP_LOG_TRACE, "", (SOCKADDR_IPX*) &permitMgrs[i].addrEncoding, "\n");
|
|
#endif
|
|
pIpx = (SOCKADDR_IPX *) &permitMgrs[i].addrEncoding;
|
|
test = *(DWORD *)((SOCKADDR_IPX *)(&permitMgrs[i].addrEncoding))->sa_netnum;
|
|
//Below checks for nodenumber regardless of netnumber if the user specified
|
|
// a netnumber of zero for the permitted IPX mgr
|
|
if (*(DWORD *)((SOCKADDR_IPX *)(&permitMgrs[i].addrEncoding))->sa_netnum == 0)
|
|
{
|
|
if (memcmp(((SOCKADDR_IPX *)source)->sa_nodenum,
|
|
((SOCKADDR_IPX *)(&permitMgrs[i].addrEncoding))->sa_nodenum,
|
|
sizeof(((SOCKADDR_IPX *)source)->sa_nodenum)) == 0)
|
|
{
|
|
fFound = TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//Compare the entire address
|
|
if (memcmp(source,
|
|
&permitMgrs[i].addrEncoding,
|
|
sizeof(((SOCKADDR_IPX *)source)->sa_netnum) +
|
|
sizeof(((SOCKADDR_IPX *)source)->sa_nodenum)) == 0)
|
|
{
|
|
fFound = TRUE;
|
|
}
|
|
}
|
|
// --------- END: PROTOCOL SPECIFIC SOCKET CODE END. ---------------
|
|
} // end switch
|
|
} // end for()
|
|
}
|
|
else
|
|
{
|
|
fFound = TRUE; // no entries means all managers allowed
|
|
} // end if
|
|
|
|
if (!fFound)
|
|
{
|
|
SNMPDBG((SNMP_LOG_TRACE, "SNMP: PDU: invalid manager filtered.\n"));
|
|
}
|
|
|
|
return fFound;
|
|
|
|
} // end filtmgrs()
|
|
|
|
|
|
//-------------------------------- END --------------------------------------
|
|
|
|
// display IPX address in 00000001.123456789ABC form
|
|
|
|
void dp_ipx(int level, char *msg1, SOCKADDR_IPX* addr, char *msg2)
|
|
{
|
|
SNMPDBG((level, "%s%02X%02X%02X%02X.%02X%02X%02X%02X%02X%02X%s",
|
|
msg1,
|
|
(unsigned char)addr->sa_netnum[0],
|
|
(unsigned char)addr->sa_netnum[1],
|
|
(unsigned char)addr->sa_netnum[2],
|
|
(unsigned char)addr->sa_netnum[3],
|
|
(unsigned char)addr->sa_nodenum[0],
|
|
(unsigned char)addr->sa_nodenum[1],
|
|
(unsigned char)addr->sa_nodenum[2],
|
|
(unsigned char)addr->sa_nodenum[3],
|
|
(unsigned char)addr->sa_nodenum[4],
|
|
(unsigned char)addr->sa_nodenum[5],
|
|
msg2));
|
|
}
|
|
|
|
//-------------------------------- TMP --------------------------------------
|
|
|
|
|
|
SNMPAPI
|
|
SNMP_FUNC_TYPE
|
|
SnmpUtilAsnAnyFree(
|
|
AsnAny * asnAny
|
|
)
|
|
{
|
|
switch (asnAny->asnType) {
|
|
|
|
case ASN_OBJECTIDENTIFIER:
|
|
SnmpUtilOidFree(&asnAny->asnValue.object);
|
|
// make sure no multiple releases
|
|
asnAny->asnValue.object.idLength = 0;
|
|
asnAny->asnValue.object.ids = NULL;
|
|
break;
|
|
|
|
case ASN_RFC1155_IPADDRESS:
|
|
case ASN_RFC1155_OPAQUE:
|
|
case ASN_OCTETSTRING:
|
|
if (asnAny->asnValue.string.dynamic) {
|
|
SnmpUtilMemFree(asnAny->asnValue.string.stream);
|
|
// make sure no multiple releases
|
|
asnAny->asnValue.string.dynamic = FALSE;
|
|
asnAny->asnValue.string.stream = NULL;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
asnAny->asnType = ASN_NULL;
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
SNMPAPI
|
|
SNMP_FUNC_TYPE
|
|
SnmpUtilAsnAnyCpy(
|
|
AsnAny * asnDst,
|
|
AsnAny * asnSrc
|
|
)
|
|
{
|
|
switch (asnSrc->asnType) {
|
|
|
|
case ASN_OBJECTIDENTIFIER:
|
|
SnmpUtilOidCpy(
|
|
&asnDst->asnValue.object,
|
|
&asnSrc->asnValue.object
|
|
);
|
|
break;
|
|
|
|
case ASN_RFC1155_IPADDRESS:
|
|
case ASN_RFC1155_OPAQUE:
|
|
case ASN_OCTETSTRING:
|
|
asnDst->asnValue.string.stream =
|
|
SnmpUtilMemAlloc(asnSrc->asnValue.string.length);
|
|
|
|
asnDst->asnValue.string.length = asnSrc->asnValue.string.length;
|
|
memcpy(
|
|
asnDst->asnValue.string.stream,
|
|
asnSrc->asnValue.string.stream,
|
|
asnDst->asnValue.string.length
|
|
);
|
|
|
|
asnDst->asnValue.string.dynamic = TRUE;
|
|
break;
|
|
|
|
default:
|
|
asnDst->asnValue = asnSrc->asnValue;
|
|
break;
|
|
}
|
|
|
|
asnDst->asnType = asnSrc->asnType;
|
|
return TRUE;
|
|
}
|