|
|
/*++ BUILD Version: 0001 // Increment this if a change has global effects
Copyright (c) 1991 Microsoft Corporation
Module Name:
mib.c
Abstract:
SNMP Extension Agent for Windows NT.
Created:
18-Feb-1995
Revision History:
--*/
#include "mib.h"
//
// Private constants & macros.
//
//
// This macro creates a MIB_ENTRY for a MIB group header.
//
#define MIB_ENTRY_HEADER(oid) \
{ \ { OID_SIZEOF(oid), (oid) }, \ -1, \ MIB_NOACCESS, \ NULL, \ ASN_RFC1155_OPAQUE, \ }
//
// This macro creates a generic MIB_ENTRY for a MIB variable.
//
#define MIB_ENTRY_ITEM(oid,field,type) \
{ \ { OID_SIZEOF(oid), (oid) }, \ FIELD_OFFSET(FTP_STATISTICS_0,field), \ MIB_ACCESS_READ, \ MIB_Stat, \ (type), \ }
//
// These macros create COUNTER and INTEGER type MIB_ENTRYs.
//
#define MIB_COUNTER(oid,field) \
MIB_ENTRY_ITEM(oid, field, ASN_RFC1155_COUNTER)
#define MIB_INTEGER(oid,field) \
MIB_ENTRY_ITEM(oid, field, ASN_INTEGER)
//
// Private types.
//
typedef UINT (*LPMIBFUNC)( UINT Action, struct _MIB_ENTRY * MibPtr, RFC1157VarBind * VarBind, LPVOID Statistics );
typedef struct _MIB_ENTRY { //
// The OID for this MIB variable.
//
AsnObjectIdentifier Oid;
//
// The offset within the statistics structure for this
// variable.
//
LONG FieldOffset;
//
// Access type (read, write, read-write, none).
//
UINT Access;
//
// Pointer to a function that manages this variable.
//
LPMIBFUNC MibFunc;
//
// Type (integer, counter, gauge, etc.)
//
BYTE Type;
} MIB_ENTRY;
//
// Private globals.
//
//
// The InternetServer section of the OID tree is organized as follows:
//
// iso(1)
// org(3)
// dod(6)
// internet(1)
// private(4)
// enterprises(1)
// microsoft(311)
// software(1)
// InternetServer(7)
// InetSrvCommon(1)
// InetSrvStatistics(1)
// FtpServer(2)
// FtpStatistics(1)
// W3Server(3)
// W3Statistics(1)
// GopherServer(4)
// GopherStatistics(1)
//
UINT OID_Prefix[] = { 1, 3, 6, 1, 4, 1, 311, 1, 7, 2 }; AsnObjectIdentifier MIB_OidPrefix = { OID_SIZEOF(OID_Prefix), OID_Prefix };
//
// OID definitions.
//
// All leaf variables have a zero appended to their OID to indicate
// that it is the only instance of this variable and that it exists.
//
UINT MIB_Statistics[] = { 1 }; UINT MIB_TotalBytesSent_HighWord[] = { 1, 1, 0 }; UINT MIB_TotalBytesSent_LowWord[] = { 1, 2, 0 }; UINT MIB_TotalBytesReceived_HighWord[] = { 1, 3, 0 }; UINT MIB_TotalBytesReceived_LowWord[] = { 1, 4, 0 }; UINT MIB_TotalFilesSent[] = { 1, 5, 0 }; UINT MIB_TotalFilesReceived[] = { 1, 6, 0 }; UINT MIB_CurrentAnonymousUsers[] = { 1, 7, 0 }; UINT MIB_CurrentNonAnonymousUsers[] = { 1, 8, 0 }; UINT MIB_TotalAnonymousUsers[] = { 1, 9, 0 }; UINT MIB_TotalNonAnonymousUsers[] = { 1, 10, 0 }; UINT MIB_MaxAnonymousUsers[] = { 1, 11, 0 }; UINT MIB_MaxNonAnonymousUsers[] = { 1, 12, 0 }; UINT MIB_CurrentConnections[] = { 1, 13, 0 }; UINT MIB_MaxConnections[] = { 1, 14, 0 }; UINT MIB_ConnectionAttempts[] = { 1, 15, 0 }; UINT MIB_LogonAttempts[] = { 1, 16, 0 };
//
// Private prototypes.
//
UINT MIB_leaf_func( UINT Action, MIB_ENTRY * MibPtr, RFC1157VarBind * VarBind, LPVOID Statistics );
UINT MIB_Stat( UINT Action, MIB_ENTRY * MibPtr, RFC1157VarBind * VarBind, LPVOID Statistics );
UINT GetNextVar( RFC1157VarBind * VarBind, MIB_ENTRY * MibPtr, LPVOID Statistics );
//
// MIB definiton
//
MIB_ENTRY Mib[] = { //
// Statistics.
//
MIB_ENTRY_HEADER( MIB_Statistics ), MIB_COUNTER( MIB_TotalBytesSent_HighWord, TotalBytesSent.HighPart ), MIB_COUNTER( MIB_TotalBytesSent_LowWord, TotalBytesSent.LowPart ), MIB_COUNTER( MIB_TotalBytesReceived_HighWord, TotalBytesReceived.HighPart ), MIB_COUNTER( MIB_TotalBytesReceived_LowWord, TotalBytesReceived.LowPart ), MIB_COUNTER( MIB_TotalFilesSent, TotalFilesSent ), MIB_COUNTER( MIB_TotalFilesReceived, TotalFilesReceived ), MIB_INTEGER( MIB_CurrentAnonymousUsers, CurrentAnonymousUsers ), MIB_INTEGER( MIB_CurrentNonAnonymousUsers, CurrentNonAnonymousUsers ), MIB_COUNTER( MIB_TotalAnonymousUsers, TotalAnonymousUsers ), MIB_COUNTER( MIB_TotalNonAnonymousUsers, TotalNonAnonymousUsers ), MIB_COUNTER( MIB_MaxAnonymousUsers, MaxAnonymousUsers ), MIB_COUNTER( MIB_MaxNonAnonymousUsers, MaxNonAnonymousUsers ), MIB_INTEGER( MIB_CurrentConnections, CurrentConnections ), MIB_COUNTER( MIB_MaxConnections, MaxConnections ), MIB_COUNTER( MIB_ConnectionAttempts, ConnectionAttempts ), MIB_COUNTER( MIB_LogonAttempts, LogonAttempts ) };
#define NUM_MIB_ENTRIES ( sizeof(Mib) / sizeof(MIB_ENTRY) )
//
// Public functions.
//
UINT ResolveVarBind( RFC1157VarBind * VarBind, UINT PduAction, LPVOID Statistics ) //
// ResolveVarBind
// Resolves a single variable binding. Modifies the variable on a GET
// or a GET-NEXT.
//
// Notes:
//
// Return Codes:
// Standard PDU error codes.
//
// Error Codes:
// None.
//
{ MIB_ENTRY *MibPtr; AsnObjectIdentifier TempOid; int CompResult; UINT i; UINT nResult; DWORD TableIndex; BOOL fTableMatch = FALSE;
//
// Search for a varbind name in the MIB.
//
MibPtr = NULL;
for( i = 0 ; i < NUM_MIB_ENTRIES ; i++ ) { //
// Create a fully qualified OID for the current item in the MIB.
//
SNMP_oidcpy( &TempOid, &MIB_OidPrefix ); SNMP_oidappend( &TempOid, &Mib[i].Oid );
//
// See if the given OID is in the MIB.
//
CompResult = SNMP_oidcmp( &VarBind->name, &TempOid ); SNMP_oidfree( &TempOid );
//
// If result is negative, only valid operation is GET-NEXT.
//
if( CompResult < 0 ) { //
// This could be the OID of a leaf (without a trailing 0) or
// it could be an invalid OID (between two valid OIDs).
//
if( PduAction == MIB_GETNEXT ) { MibPtr = &Mib[i];
SNMP_oidfree( &VarBind->name ); SNMP_oidcpy( &VarBind->name, &MIB_OidPrefix ); SNMP_oidappend( &VarBind->name, &MibPtr->Oid );
if( ( MibPtr->Type != ASN_RFC1155_OPAQUE ) && ( MibPtr->Type != ASN_SEQUENCE ) ) { PduAction = MIB_GET; } } else { nResult = SNMP_ERRORSTATUS_NOSUCHNAME; goto Exit; }
break; } else if( CompResult == 0 ) { //
// Found one!
//
MibPtr = &Mib[i]; break; } }
if( i < NUM_MIB_ENTRIES ) { //
// The associated function pointer will be NULL only if the
// match was with a group OID.
//
if( MibPtr->MibFunc == NULL ) { if( PduAction == MIB_GETNEXT ) { nResult = GetNextVar( VarBind, MibPtr, Statistics ); } else { nResult = SNMP_ERRORSTATUS_NOSUCHNAME; }
goto Exit; } } else { nResult = SNMP_ERRORSTATUS_NOSUCHNAME; goto Exit; }
//
// Call the associated function to process the request.
//
nResult = (MibPtr->MibFunc)( PduAction, MibPtr, VarBind, Statistics );
Exit:
return nResult;
} // ResolveVarBind
//
// Private functions.
//
//
// MIB_leaf_func
// Performs generic actions on LEAF variables in the MIB.
//
// Notes:
//
// Return Codes:
// Standard PDU error codes.
//
// Error Codes:
// None.
//
UINT MIB_leaf_func( UINT Action, MIB_ENTRY * MibPtr, RFC1157VarBind * VarBind, LPVOID Statistics ) { UINT Result; DWORD Value;
switch( Action ) { case MIB_GETNEXT : //
// Determine if we're at the end of our MIB.
//
if( ( MibPtr - Mib ) >= NUM_MIB_ENTRIES ) { Result = SNMP_ERRORSTATUS_NOSUCHNAME; goto Exit; }
Result = GetNextVar( VarBind, MibPtr, Statistics );
if (Result != SNMP_ERRORSTATUS_NOERROR) { goto Exit; } break;
case MIB_GETFIRST : case MIB_GET :
//
// Make sure that this variable's ACCESS is GET'able.
//
if( ( MibPtr->Access != MIB_ACCESS_READ ) && ( MibPtr->Access != MIB_ACCESS_READWRITE ) ) { Result = SNMP_ERRORSTATUS_NOSUCHNAME; goto Exit; }
//
// Setup varbind's return value.
//
VarBind->value.asnType = MibPtr->Type;
Value = *(LPDWORD)( (LPBYTE)Statistics + MibPtr->FieldOffset );
switch( VarBind->value.asnType ) { case ASN_RFC1155_COUNTER: VarBind->value.asnValue.number = (AsnCounter)Value; break;
case ASN_RFC1155_GAUGE: case ASN_INTEGER: VarBind->value.asnValue.number = (AsnInteger)Value; break;
case ASN_RFC1155_IPADDRESS: case ASN_OCTETSTRING: //
// Not supported for this MIB (yet).
//
Result = SNMP_ERRORSTATUS_GENERR; goto Exit;
default: Result = SNMP_ERRORSTATUS_GENERR; goto Exit; } break;
case MIB_SET:
//
// We don't support settable variables (yet).
//
Result = SNMP_ERRORSTATUS_NOSUCHNAME; goto Exit;
default: Result = SNMP_ERRORSTATUS_GENERR; goto Exit; }
Result = SNMP_ERRORSTATUS_NOERROR;
Exit:
return Result;
} // MIB_leaf_func
//
// MIB_Stat
// Performs specific actions on the different MIB variable.
//
// Notes:
//
// Return Codes:
// Standard PDU error codes.
//
// Error Codes:
// None.
//
UINT MIB_Stat( UINT Action, MIB_ENTRY * MibPtr, RFC1157VarBind * VarBind, LPVOID Statistics ) { UINT Result;
switch( Action ) { case MIB_SET : case MIB_GETNEXT : Result = MIB_leaf_func( Action, MibPtr, VarBind, Statistics ); break;
case MIB_GETFIRST : case MIB_GET : //
// If we have no statistics structure, bail.
//
if( Statistics == NULL ) { Result = SNMP_ERRORSTATUS_GENERR; break; }
//
// If there's no field offset associated with the current
// entry, also bail.
//
if( MibPtr->FieldOffset == -1 ) { Result = SNMP_ERRORSTATUS_GENERR; break; }
//
// Call the generic leaf function to perform the action.
//
Result = MIB_leaf_func( Action, MibPtr, VarBind, Statistics ); break;
default : Result = SNMP_ERRORSTATUS_GENERR; break; }
return Result;
} // MIB_Stat
UINT GetNextVar( RFC1157VarBind * VarBind, MIB_ENTRY * MibPtr, LPVOID Statistics ) { UINT Result; INT i;
//
// Calculate the current index within the MIB array.
//
i = DIFF( MibPtr - Mib );
//
// Validate we have a reasonable value.
//
if( ( i < 0 ) || ( i >= NUM_MIB_ENTRIES ) ) { return SNMP_ERRORSTATUS_NOSUCHNAME; }
//
// Scan through the remaining MIB entries.
//
for( i++ ; i < NUM_MIB_ENTRIES ; i++ ) { MIB_ENTRY * NextMib;
NextMib = &Mib[i];
//
// Setup varbind name of next MIB variable.
//
SNMP_oidfree( &VarBind->name ); SNMP_oidcpy( &VarBind->name, &MIB_OidPrefix ); SNMP_oidappend( &VarBind->name, &NextMib->Oid );
//
// 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( ( NextMib->MibFunc != NULL ) && ( NextMib->Type != ASN_RFC1155_OPAQUE ) ) { Result = (NextMib->MibFunc)( MIB_GETFIRST, NextMib, VarBind, Statistics ); break; } }
if( i >= NUM_MIB_ENTRIES ) { Result = SNMP_ERRORSTATUS_NOSUCHNAME; }
return Result;
} // GetNextVar
|