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.
621 lines
15 KiB
621 lines
15 KiB
/*++ 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
|
|
|