558 lines
15 KiB
C
558 lines
15 KiB
C
|
/*++ BUILD Version: 0001 // Increment this if a change has global effects.
|
|||
|
|
|||
|
Copyright (c) 1995 Microsoft Corporation
|
|||
|
|
|||
|
Module Name :
|
|||
|
|
|||
|
mib.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This defines Auxiliary functions for defining an SNMP Extension Agent
|
|||
|
for collecting and querying Statistical information.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Murali R. Krishnan ( MuraliK ) 23-Feb-1995
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
User Mode -- Win32
|
|||
|
|
|||
|
Project:
|
|||
|
|
|||
|
SNMP Extension DLL for Gopher Service DLL
|
|||
|
|
|||
|
Functions Exported:
|
|||
|
|
|||
|
UINT ResolveVarBinding();
|
|||
|
UINT MibStatisticsWorker();
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
|
|||
|
/************************************************************
|
|||
|
* Include Headers
|
|||
|
************************************************************/
|
|||
|
|
|||
|
# include "mib.h"
|
|||
|
|
|||
|
# include "dbgutil.h"
|
|||
|
|
|||
|
static UINT
|
|||
|
MibLeafFunction(
|
|||
|
IN OUT RFC1157VarBind * pRfcVarBinding,
|
|||
|
IN UINT pduAction,
|
|||
|
IN struct _MIB_ENTRY * pMibeCurrent,
|
|||
|
IN struct _MIB_ENTRIES * pMibEntries,
|
|||
|
IN LPVOID pStatistics
|
|||
|
);
|
|||
|
|
|||
|
static UINT
|
|||
|
MibGetNextVar(
|
|||
|
IN OUT RFC1157VarBind * pRfcVarBinding,
|
|||
|
IN MIB_ENTRY * pMibeCurrent,
|
|||
|
IN MIB_ENTRIES * pMibEntries,
|
|||
|
IN LPVOID pStatistics
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
static VOID
|
|||
|
PrintAsnObjectIdentifier( IN char * pszOidDescription,
|
|||
|
IN AsnObjectIdentifier * pAsno)
|
|||
|
{
|
|||
|
|
|||
|
# if DBG
|
|||
|
|
|||
|
UINT len = pAsno->idLength;
|
|||
|
UINT i;
|
|||
|
|
|||
|
DBG_ASSERT( pAsno != NULL);
|
|||
|
|
|||
|
DBGPRINTF( ( DBG_CONTEXT,
|
|||
|
"Printing Oid %s = %08x. Length = %u.\n",
|
|||
|
pszOidDescription,
|
|||
|
pAsno, len));
|
|||
|
|
|||
|
for(i = 0; i < len; i++) {
|
|||
|
|
|||
|
DBGPRINTF( ( DBG_CONTEXT,
|
|||
|
"AsnOid[ %u] = %u\n",
|
|||
|
i, pAsno->ids[i]));
|
|||
|
}
|
|||
|
|
|||
|
# endif // DBG
|
|||
|
|
|||
|
return;
|
|||
|
} // PrintAsnObjectIdentifier()
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
/************************************************************
|
|||
|
* Functions
|
|||
|
************************************************************/
|
|||
|
|
|||
|
UINT
|
|||
|
ResolveVarBinding(
|
|||
|
IN OUT RFC1157VarBind * pRfcVarBinding,
|
|||
|
IN BYTE pduAction,
|
|||
|
IN LPVOID pStatistics,
|
|||
|
IN LPMIB_ENTRIES pMibEntries
|
|||
|
)
|
|||
|
/*++
|
|||
|
Description:
|
|||
|
This function resolves a single variable binding. Modifies the variable
|
|||
|
on a GET or a GET-NEXT.
|
|||
|
|
|||
|
Arguments:
|
|||
|
pRfcVarBinding pointer to RFC Variable Bindings
|
|||
|
pduAction Protocol Data Unit Action specified.
|
|||
|
pStatistics pointer to statisitcs data structure containing
|
|||
|
values of counter data.
|
|||
|
pMibEntries pointer to MIB_ENTRIES context information
|
|||
|
which contains prefix, array of MIB_ENTRIES and
|
|||
|
count of the entries.
|
|||
|
Returns:
|
|||
|
Standard PDU error codes.
|
|||
|
|
|||
|
Note:
|
|||
|
--*/
|
|||
|
{
|
|||
|
AsnObjectIdentifier AsnTempOid;
|
|||
|
LPMIB_ENTRY pMibScan;
|
|||
|
UINT pduResult = SNMP_ERRORSTATUS_NOERROR;
|
|||
|
LPMIB_ENTRY pMibUpperBound =
|
|||
|
pMibEntries->prgMibEntry + pMibEntries->cMibEntries;
|
|||
|
|
|||
|
//
|
|||
|
// Search for the variable binding name in the mib.
|
|||
|
//
|
|||
|
|
|||
|
IF_DEBUG( SNMP_RESOLVE) {
|
|||
|
|
|||
|
DBGPRINTF( ( DBG_CONTEXT,
|
|||
|
" ResolveVarBinding( Var=%08x, Action=%x) called.\n",
|
|||
|
pRfcVarBinding, pduAction));
|
|||
|
|
|||
|
PrintAsnObjectIdentifier( " Variable to Resolve",
|
|||
|
&pRfcVarBinding->name);
|
|||
|
}
|
|||
|
|
|||
|
for( pMibScan = pMibEntries->prgMibEntry;
|
|||
|
pMibScan < pMibUpperBound;
|
|||
|
pMibScan++) {
|
|||
|
|
|||
|
int iCmpResult;
|
|||
|
|
|||
|
//
|
|||
|
// Create a fully qualified OID for the current item in the MIB.
|
|||
|
// and use it for comparing against variable to be resolved.
|
|||
|
//
|
|||
|
|
|||
|
SNMP_oidcpy( &AsnTempOid, pMibEntries->pOidPrefix);
|
|||
|
SNMP_oidappend( &AsnTempOid, &pMibScan->asnOid);
|
|||
|
|
|||
|
iCmpResult = SNMP_oidcmp( &pRfcVarBinding->name, &AsnTempOid);
|
|||
|
SNMP_oidfree( &AsnTempOid);
|
|||
|
|
|||
|
IF_DEBUG( SNMP_RESOLVE) {
|
|||
|
|
|||
|
DBGPRINTF( ( DBG_CONTEXT,
|
|||
|
" Comparing with suffix Oid %08x yields %d\n",
|
|||
|
&pMibScan->asnOid, iCmpResult));
|
|||
|
PrintAsnObjectIdentifier( " StatisticsSuffix",
|
|||
|
&pMibScan->asnOid);
|
|||
|
}
|
|||
|
|
|||
|
if ( iCmpResult == 0) {
|
|||
|
|
|||
|
//
|
|||
|
// Found a match. Stop the search and process.
|
|||
|
//
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
} else
|
|||
|
if ( iCmpResult < 0) {
|
|||
|
|
|||
|
//
|
|||
|
// This could be the OID of a leaf ( withoug a trailing 0) or
|
|||
|
// it could contain an invalid OID ( between valid OIDs).
|
|||
|
//
|
|||
|
|
|||
|
if ( pduAction == MIB_GETNEXT) {
|
|||
|
|
|||
|
//
|
|||
|
// Advance the variable binding to next entry
|
|||
|
//
|
|||
|
SNMP_oidfree( &pRfcVarBinding->name);
|
|||
|
SNMP_oidcpy( &pRfcVarBinding->name,
|
|||
|
pMibEntries->pOidPrefix);
|
|||
|
SNMP_oidappend( &pRfcVarBinding->name, &pMibScan->asnOid);
|
|||
|
|
|||
|
if ( ( pMibScan->bType != ASN_RFC1155_OPAQUE) &&
|
|||
|
( pMibScan->bType != ASN_SEQUENCE)) {
|
|||
|
|
|||
|
pduAction = MIB_GET;
|
|||
|
}
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
pduResult = SNMP_ERRORSTATUS_NOSUCHNAME;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Stop and process the appropriate entry.
|
|||
|
//
|
|||
|
|
|||
|
break;
|
|||
|
} // ( iCmpResult < 0)
|
|||
|
|
|||
|
} // for
|
|||
|
|
|||
|
|
|||
|
if ( pMibScan >= pMibUpperBound) {
|
|||
|
|
|||
|
pduResult = SNMP_ERRORSTATUS_NOSUCHNAME;
|
|||
|
}
|
|||
|
|
|||
|
if ( pduResult == SNMP_ERRORSTATUS_NOERROR) {
|
|||
|
|
|||
|
//
|
|||
|
// A match is found or further processing is required.
|
|||
|
//
|
|||
|
|
|||
|
DBG_ASSERT( pMibScan < pMibUpperBound);
|
|||
|
if ( pMibScan->pMibFunc == NULL) {
|
|||
|
|
|||
|
//
|
|||
|
// This happens only if the match is for Group OID
|
|||
|
//
|
|||
|
|
|||
|
pduResult = ( ( pduAction != MIB_GETNEXT) ?
|
|||
|
SNMP_ERRORSTATUS_NOSUCHNAME:
|
|||
|
MibGetNextVar( pRfcVarBinding,
|
|||
|
pMibScan,
|
|||
|
pMibEntries,
|
|||
|
pStatistics));
|
|||
|
} else {
|
|||
|
|
|||
|
pduResult = ( pMibScan->pMibFunc) ( pRfcVarBinding,
|
|||
|
pduAction,
|
|||
|
pMibScan,
|
|||
|
pMibEntries,
|
|||
|
pStatistics);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
IF_DEBUG( SNMP_RESOLVE) {
|
|||
|
|
|||
|
DBGPRINTF( ( DBG_CONTEXT,
|
|||
|
" ResolveVarBinding returns %u.\n",
|
|||
|
pduResult));
|
|||
|
}
|
|||
|
|
|||
|
return ( pduResult);
|
|||
|
|
|||
|
} // ResolveVarBinding()
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
UINT
|
|||
|
MibStatisticsWorker(
|
|||
|
IN OUT RFC1157VarBind * pRfcVarBinding,
|
|||
|
IN UINT pduAction,
|
|||
|
IN struct _MIB_ENTRY * pMibeCurrent,
|
|||
|
IN struct _MIB_ENTRIES * pMibEntries,
|
|||
|
IN LPVOID pStatistics
|
|||
|
)
|
|||
|
/*++
|
|||
|
This function resolves the variables assuming that there is statistical
|
|||
|
information ( sequence of counters) in the data passed in pStatistics.
|
|||
|
|
|||
|
Arguments:
|
|||
|
pRfcVarBind pointer to RFC variable binding to be resolved.
|
|||
|
pduAction protocol data unit action to be taken.
|
|||
|
pMibeCurrent pointer to MIB_ENTRY which is o be used for resolution.
|
|||
|
pMibEntries pointer to MIB_ENTRIES structure to be used
|
|||
|
as context for resolving and performing the action.
|
|||
|
pStatistics pointer to sequence of counters used for data resolution.
|
|||
|
|
|||
|
|
|||
|
Returns:
|
|||
|
Standard PDU error codes.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
UINT pduResult = SNMP_ERRORSTATUS_NOERROR;
|
|||
|
// default indicating action to be done at end of switch
|
|||
|
|
|||
|
switch( pduAction) {
|
|||
|
|
|||
|
case MIB_SET:
|
|||
|
case MIB_GETNEXT:
|
|||
|
|
|||
|
// action is performed at the end of switch statement.
|
|||
|
break;
|
|||
|
|
|||
|
|
|||
|
case MIB_GETFIRST:
|
|||
|
case MIB_GET:
|
|||
|
|
|||
|
//
|
|||
|
// If no statistics do no action.
|
|||
|
// If this is the header field ( non-leaf) do no action
|
|||
|
// Otherwise, perform action as if this is the leaf node.
|
|||
|
//
|
|||
|
|
|||
|
if ( pStatistics == NULL || pMibeCurrent->lFieldOffset == -1) {
|
|||
|
|
|||
|
pduResult = SNMP_ERRORSTATUS_GENERR;
|
|||
|
}
|
|||
|
|
|||
|
// Action on this node is performed at the end of the switch statement.
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
pduResult = SNMP_ERRORSTATUS_GENERR;
|
|||
|
break;
|
|||
|
} // switch()
|
|||
|
|
|||
|
|
|||
|
if ( pduResult == SNMP_ERRORSTATUS_NOERROR) {
|
|||
|
|
|||
|
//
|
|||
|
// Use the generic leaf function to perform the action specified.
|
|||
|
//
|
|||
|
pduResult = MibLeafFunction( pRfcVarBinding, pduAction, pMibeCurrent,
|
|||
|
pMibEntries, pStatistics);
|
|||
|
}
|
|||
|
|
|||
|
return ( pduResult);
|
|||
|
|
|||
|
} // MibStatisticsWorker()
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
static UINT
|
|||
|
MibLeafFunction(
|
|||
|
IN OUT RFC1157VarBind * pRfcVarBinding,
|
|||
|
IN UINT pduAction,
|
|||
|
IN struct _MIB_ENTRY * pMibeCurrent,
|
|||
|
IN struct _MIB_ENTRIES * pMibEntries,
|
|||
|
IN LPVOID pStatistics
|
|||
|
)
|
|||
|
/*++
|
|||
|
This function resolves the variables assuming that there is statistical
|
|||
|
information ( sequence of counters) in the data passed in pStatistics
|
|||
|
and that this is a leaf node of the MIB tree.
|
|||
|
This is a generic function for leaf nodes.
|
|||
|
|
|||
|
Arguments:
|
|||
|
pRfcVarBind pointer to RFC variable binding to be resolved.
|
|||
|
pduAction protocol data unit action to be taken.
|
|||
|
pMibeCurrent pointer to MIB_ENTRY which is o be used for resolution.
|
|||
|
pMibEntries pointer to MIB_ENTRIES structure to be used
|
|||
|
as context for resolving and performing the action.
|
|||
|
pStatistics pointer to sequence of counters used for data resolution.
|
|||
|
|
|||
|
|
|||
|
Returns:
|
|||
|
Standard PDU error codes.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
UINT pduResult = SNMP_ERRORSTATUS_NOSUCHNAME; // default is error value.
|
|||
|
|
|||
|
switch( pduAction ) {
|
|||
|
|
|||
|
case MIB_GETNEXT:
|
|||
|
|
|||
|
//
|
|||
|
// Determine if we're within the range and not at the end.
|
|||
|
// If not within the range the above default pduResult == NOSUCHNAME
|
|||
|
// is the required error message.
|
|||
|
//
|
|||
|
|
|||
|
if ( ( pMibeCurrent >= pMibEntries->prgMibEntry) &&
|
|||
|
( pMibeCurrent <
|
|||
|
( pMibEntries->prgMibEntry + pMibEntries->cMibEntries))) {
|
|||
|
|
|||
|
pduResult = MibGetNextVar( pRfcVarBinding,
|
|||
|
pMibeCurrent,
|
|||
|
pMibEntries,
|
|||
|
pStatistics);
|
|||
|
}
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
case MIB_GETFIRST:
|
|||
|
case MIB_GET:
|
|||
|
|
|||
|
//
|
|||
|
// Make sure that this variable's ACCESS is GET'able.
|
|||
|
// If the access prohibits from GETting it, report error as
|
|||
|
// NOSUCHNAME ( default value of pduResult in initialization above)
|
|||
|
//
|
|||
|
|
|||
|
if(( pMibeCurrent->uiAccess == MIB_ACCESS_READ ) ||
|
|||
|
( pMibeCurrent->uiAccess == MIB_ACCESS_READWRITE ) ) {
|
|||
|
|
|||
|
DWORD dwValue;
|
|||
|
|
|||
|
//
|
|||
|
// Setup pRfcVarBinding's return value.
|
|||
|
//
|
|||
|
|
|||
|
DBG_ASSERT( pStatistics != NULL);
|
|||
|
|
|||
|
pRfcVarBinding->value.asnType = pMibeCurrent->bType;
|
|||
|
dwValue = *( (LPDWORD )((LPBYTE )pStatistics +
|
|||
|
pMibeCurrent->lFieldOffset));
|
|||
|
|
|||
|
pduResult = SNMP_ERRORSTATUS_NOERROR; // we found a value.
|
|||
|
|
|||
|
switch( pMibeCurrent->bType) {
|
|||
|
|
|||
|
case ASN_RFC1155_GAUGE:
|
|||
|
pRfcVarBinding->value.asnValue.gauge = (AsnGauge ) dwValue;
|
|||
|
break;
|
|||
|
|
|||
|
case ASN_RFC1155_COUNTER:
|
|||
|
pRfcVarBinding->value.asnValue.counter = (AsnCounter ) dwValue;
|
|||
|
break;
|
|||
|
|
|||
|
case ASN_INTEGER:
|
|||
|
pRfcVarBinding->value.asnValue.number = (AsnInteger ) dwValue;
|
|||
|
break;
|
|||
|
|
|||
|
case ASN_RFC1155_IPADDRESS:
|
|||
|
case ASN_OCTETSTRING:
|
|||
|
//
|
|||
|
// Not supported for this MIB (yet).
|
|||
|
// Fall through to indicate generic error.
|
|||
|
//
|
|||
|
|
|||
|
default:
|
|||
|
|
|||
|
//
|
|||
|
// Sorry! Type in Mibe does not suit our purpose.
|
|||
|
// Indicate generic error.
|
|||
|
//
|
|||
|
pduResult = SNMP_ERRORSTATUS_GENERR;
|
|||
|
break;
|
|||
|
} // innner switch
|
|||
|
|
|||
|
} // if ( valid read access)
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
case MIB_SET:
|
|||
|
|
|||
|
//
|
|||
|
// We don't support settable variables (yet).
|
|||
|
// Fall through for error.
|
|||
|
//
|
|||
|
|
|||
|
default:
|
|||
|
pduResult = SNMP_ERRORSTATUS_GENERR;
|
|||
|
break;
|
|||
|
} // switch ( pduAction)
|
|||
|
|
|||
|
|
|||
|
return ( pduResult);
|
|||
|
|
|||
|
} // MibLeafFunction()
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
static UINT
|
|||
|
MibGetNextVar(
|
|||
|
IN OUT RFC1157VarBind * pRfcVarBinding,
|
|||
|
IN MIB_ENTRY * pMibeCurrent,
|
|||
|
IN MIB_ENTRIES * pMibEntries,
|
|||
|
IN LPVOID pStatistics)
|
|||
|
/*++
|
|||
|
Description:
|
|||
|
This function sets the binding variable to iterate to the next variable.
|
|||
|
|
|||
|
Arguments:
|
|||
|
pRfcVarBind pointer to RFC variable binding to be resolved.
|
|||
|
pMibeCurrent pointer to MIB_ENTRY which is o be used for resolution.
|
|||
|
pMibEntries pointer to MIB_ENTRIES structure to be used
|
|||
|
as context for resolving and performing the action.
|
|||
|
pStatistics pointer to sequence of counters used for data resolution.
|
|||
|
|
|||
|
Returns:
|
|||
|
PDU Error Codes.
|
|||
|
--*/
|
|||
|
{
|
|||
|
UINT pduResult = SNMP_ERRORSTATUS_NOSUCHNAME;
|
|||
|
LPMIB_ENTRY pMibUpperBound =
|
|||
|
pMibEntries->prgMibEntry + pMibEntries->cMibEntries;
|
|||
|
|
|||
|
//
|
|||
|
// If within the range of MIB ENTRIES process.
|
|||
|
//
|
|||
|
|
|||
|
if ( pMibeCurrent >= pMibEntries->prgMibEntry) {
|
|||
|
|
|||
|
//
|
|||
|
// Scan through the remaining MIB Entries
|
|||
|
//
|
|||
|
|
|||
|
LPMIB_ENTRY pMibeScan;
|
|||
|
|
|||
|
for( pMibeScan = pMibeCurrent+1;
|
|||
|
pMibeScan < pMibUpperBound;
|
|||
|
pMibeScan++ ) {
|
|||
|
|
|||
|
//
|
|||
|
// Setup variable bindings for the next MIB variable
|
|||
|
//
|
|||
|
|
|||
|
SNMP_oidfree( &pRfcVarBinding->name);
|
|||
|
SNMP_oidcpy( &pRfcVarBinding->name, pMibEntries->pOidPrefix);
|
|||
|
SNMP_oidappend( &pRfcVarBinding->name, &pMibeScan->asnOid);
|
|||
|
|
|||
|
//
|
|||
|
// If the function pointer is not NULL and the type of the MIB
|
|||
|
// variable is anything but OPAQUE, then call the function to
|
|||
|
// process the MIB variable.
|
|||
|
//
|
|||
|
|
|||
|
if(( pMibeScan->pMibFunc != NULL ) &&
|
|||
|
( pMibeScan->bType != ASN_RFC1155_OPAQUE ) ) {
|
|||
|
|
|||
|
pduResult = ( pMibeScan->pMibFunc)( pRfcVarBinding,
|
|||
|
MIB_GETFIRST,
|
|||
|
pMibeScan,
|
|||
|
pMibEntries,
|
|||
|
pStatistics);
|
|||
|
break;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// On failure in the scan, pduResult will have default value
|
|||
|
// as initialized above in declaration.
|
|||
|
//
|
|||
|
|
|||
|
} // for
|
|||
|
}
|
|||
|
|
|||
|
return ( pduResult);
|
|||
|
|
|||
|
} // MibGetNextVar()
|
|||
|
|
|||
|
/************************ End of File ***********************/
|