windows-nt/Source/XPSP1/NT/inetsrv/iis/svcs/ftp/mib/mib.c
2020-09-26 16:20:57 +08:00

622 lines
14 KiB
C

/*++ 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