www.pudn.com > snmp.rar > snmp.c


/*++ 
 
Copyright (c) 1992-1996  Microsoft Corporation 
 
Module Name: 
 
    snmp.c 
 
Abstract: 
 
    Contains routines and definitions that are independant to any SNMP API. 
 
Environment: 
 
    User Mode - Win32 
 
Revision History: 
 
    10-May-1996 DonRyan 
        Removed banner from Technology Dynamics, Inc. 
 
--*/ 
 
#ifdef _SNMPDLL_ 
//--------------------------- WINDOWS DEPENDENCIES -------------------------- 
 
#ifndef DOS 
#include  
#include  
#include  
#include  
#include  
#endif 
 
//--------------------------- STANDARD DEPENDENCIES -- #include ---- 
 
#include  
#include  
#include  
#include  
#include  
#include  
 
//--------------------------- MODULE DEPENDENCIES -- #include"xxxxx.h" ------ 
 
//--------------------------- SELF-DEPENDENCY -- ONE #include"module.h" ----- 
 
#include  
#include  
#include  
#include  
#include  
 
//--------------------------- PUBLIC VARIABLES --(same as in module.h file)-- 
 
DWORD g_uptimeReference = 0; 
DWORD g_platformId = 0; 
 
INT g_nLogType  = SNMP_OUTPUT_TO_DEBUGGER;   
INT g_nLogLevel = SNMP_LOG_SILENT;     
 
AsnObjectIdentifier * g_enterprise = NULL; 
 
#if DBG 
DWORD g_nBytesTotal = 0; 
#endif 
 
//--------------------------- PRIVATE CONSTANTS ----------------------------- 
 
#define MAX_DEBUG_LEN 512 
 
//--------------------------- PRIVATE STRUCTS ------------------------------- 
 
//--------------------------- PRIVATE VARIABLES ----------------------------- 
 
static UINT idsWindowsNTWorkstation[] = {1,3,6,1,4,1,311,1,1,3,1,1}; 
static UINT idsWindowsNTServer[]      = {1,3,6,1,4,1,311,1,1,3,1,2}; 
static UINT idsWindowsNTDC[]          = {1,3,6,1,4,1,311,1,1,3,1,3}; 
static UINT idsWindows[]              = {1,3,6,1,4,1,311,1,1,3,2}; 
 
static AsnObjectIdentifier oidWindowsNTWorkstation = {  
    sizeof(idsWindowsNTWorkstation)/sizeof(UINT),  
    idsWindowsNTWorkstation  
    }; 
 
static AsnObjectIdentifier oidWindowsNTServer = {  
    sizeof(idsWindowsNTServer)/sizeof(UINT),  
    idsWindowsNTServer  
    }; 
 
static AsnObjectIdentifier oidWindowsNTDC = {  
    sizeof(idsWindowsNTDC)/sizeof(UINT),  
    idsWindowsNTDC  
    }; 
 
static AsnObjectIdentifier oidWindows = {  
    sizeof(idsWindows)/sizeof(UINT),  
    idsWindows  
    }; 
 
//--------------------------- PRIVATE MACROS -------------------------------- 
 
#define bcopy(slp, dlp, size)   (void)memcpy(dlp, slp, size) 
 
//--------------------------- PRIVATE PROTOTYPES ---------------------------- 
 
//--------------------------- PRIVATE PROCEDURES ---------------------------- 
 
AsnObjectIdentifier * 
InitializeEnterpriseOID( 
    ) 
{ 
    // default to generic windows enterprise oid 
    AsnObjectIdentifier * enterprise = &oidWindows; 
 
    // check to see if the platform is winnt 
    if (g_platformId == VER_PLATFORM_WIN32_NT) { 
 
        HMODULE NtDllHandle = NULL; 
        FARPROC lpfnRtlGetNtProductType = NULL; 
        NT_PRODUCT_TYPE NtProductType; 
 
        // assume this is just a workstation         
        enterprise = &oidWindowsNTWorkstation; 
 
        // load the internal utility library 
        NtDllHandle = LoadLibrary(TEXT("ntdll.dll")); 
 
        // validate handle         
        if (NtDllHandle) { 
 
            // resolve address 
            lpfnRtlGetNtProductType = GetProcAddress( 
                                            NtDllHandle, 
                                            TEXT("RtlGetNtProductType") 
                                            ); 
            // validate pointer 
            if (lpfnRtlGetNtProductType) { 
 
                // let the system determine product type 
                (*lpfnRtlGetNtProductType)(&NtProductType); 
 
                // point to the correct enterprise oid 
                if (NtProductType == NtProductServer) { 
 
                    // this is a stand-alone server 
                    enterprise = &oidWindowsNTServer; 
 
                } else if (NtProductType == NtProductLanManNt) { 
 
                    // this is a PDC or a BDC 
                    enterprise = &oidWindowsNTDC; 
                } 
            } 
 
            // unload library  
            FreeLibrary(NtDllHandle); 
        } 
    } 
 
    SNMPDBG(( 
        SNMP_LOG_TRACE,  
        "SNMP: INIT: enterprise is %s.\n",  
        SnmpUtilOidToA(enterprise) 
        )); 
 
    return enterprise; 
} 
 
//--------------------------- PUBLIC PROCEDURES ----------------------------- 
#else  // _SNMPDLL_ 
#include  
#endif // _SNMPDLL_ 
 
#ifdef _SNMPDLL_ 
 
BOOLEAN 
InitializeDLL( 
    IN PVOID DllHandle, 
    IN ULONG Reason, 
    IN LPVOID lpReserved OPTIONAL 
    ) 
{ 
    WSADATA wsaData; 
 
    if (Reason == DLL_PROCESS_ATTACH)  
        { 
        OSVERSIONINFO osInfo;     
 
        osInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); 
 
        if (!GetVersionEx(&osInfo)) 
            return FALSE; 
 
        if ((osInfo.dwPlatformId != VER_PLATFORM_WIN32_NT) && 
            (osInfo.dwPlatformId != VER_PLATFORM_WIN32_WINDOWS)) 
            return FALSE; 
 
        g_platformId = osInfo.dwPlatformId; 
        g_enterprise = InitializeEnterpriseOID(); 
 
        DisableThreadLibraryCalls(DllHandle); 
 
        if (WSAStartup(0x0101, &wsaData)) 
            { 
            WSACleanup(); 
            return FALSE; 
            } 
        } 
    else if (Reason == DLL_PROCESS_DETACH) 
        { 
        WSACleanup(); 
        } 
 
    return TRUE; 
 
} // InitializeDLL 
 
// 
// SnmpSvcInitUptime 
//    Initializes global shared variable. 
// 
// Notes: 
// 
// Return Codes: 
//    None. 
// 
// Error Codes: 
//    None. 
// 
DWORD 
SNMP_FUNC_TYPE SnmpSvcInitUptime( 
        ) 
{ 
    g_uptimeReference = GetCurrentTime(); 
    return g_uptimeReference; 
 
} // SnmpSvcInitUptime 
 
// 
// SnmpSvcGetUptime 
//    Determine uptime via global shared variable. 
// 
// Notes: 
// 
// Return Codes: 
//    None. 
// 
// Error Codes: 
//    None. 
// 
DWORD 
SNMP_FUNC_TYPE SnmpSvcGetUptime( 
        ) 
{ 
    return ((GetCurrentTime() - g_uptimeReference) / 10); 
 
} // SnmpSvcGetUptime 
 
// 
// SnmpSvcBufRevAndCpy 
//    Copy the contents of the specified buffer into the new buffer, and 
//    reverse the contents. 
// 
// Notes: 
// 
// Return Codes: 
//    None. 
// 
// Error Codes: 
//    None. 
// 
VOID  
SNMP_FUNC_TYPE SnmpSvcBufRevAndCpy( 
        OUT BYTE *szDest,  // Destination buffer 
        IN BYTE *szSource, // Source buffer 
        IN UINT nLen       // Length of buffers 
        ) 
 
{ 
UINT I; 
 
 
   I = 0; 
   while ( I < nLen ) 
      { 
      szDest[I] = szSource[nLen - I - 1]; 
      I++; 
      } 
} // SnmpSvcBufRevAndCpy 
 
 
 
// 
// SnmpSvcBufRevInPlace 
//    Reverse the contents of the specified buffer. 
// 
// Notes: 
// 
// Return Codes: 
//    None. 
// 
// Error Codes: 
//    None. 
// 
VOID  
SNMP_FUNC_TYPE SnmpSvcBufRevInPlace( 
        IN OUT BYTE *szStr, // Buffer to reverse 
        IN UINT nLen        // Length of buffer 
        ) 
 
{ 
UINT I; 
BYTE nTemp; 
 
   for ( I=0;I < nLen/2;I++ ) 
      { 
      nTemp           = szStr[I]; 
      szStr[I]        = szStr[nLen - I - 1]; 
      szStr[nLen - I - 1] = nTemp; 
      } 
} // SnmpSvcBufRevInPlace 
 
#endif // _SNMPDLL_ 
 
 
// 
// SnmpUtilOidCpy 
//    Copy an object identifier. 
// 
// Notes: 
//    This routine is responsible for allocating enough memory to contain 
//    the new identifier. 
// 
// Return Codes: 
//    SNMPAPI_NOERROR 
//    SNMPAPI_ERROR 
// 
// Error Codes: 
//    SNMP_MEM_ALLOC_ERROR 
// 
SNMPAPI 
SNMP_FUNC_TYPE SnmpUtilOidCpy( 
           OUT AsnObjectIdentifier *DestObjId, // Destination OID 
           IN AsnObjectIdentifier *SrcObjId    // Source OID 
           ) 
 
{ 
SNMPAPI nResult; 
 
 
   // Alloc space for new object id 
   if ( NULL == 
        (DestObjId->ids = (UINT *) SnmpUtilMemAlloc((sizeof(UINT) * SrcObjId->idLength))) ) 
      { 
      SetLastError( SNMP_MEM_ALLOC_ERROR ); 
 
      nResult = SNMPAPI_ERROR; 
      goto Exit; 
      } 
 
   // Set length 
   DestObjId->idLength = SrcObjId->idLength; 
 
   // Copy the object id elements 
   memcpy( DestObjId->ids, SrcObjId->ids, DestObjId->idLength * sizeof(UINT) ); 
 
   nResult = SNMPAPI_NOERROR; 
 
Exit: 
   return nResult; 
} // SnmpUtilOidCpy 
 
 
 
// 
// SnmpUtilOidAppend 
//    Append source OID to destination OID 
// 
// Notes: 
//    If memory cannot be allocated to accommodate the extended OID, then 
//    the original OID is lost. 
// 
// Return Codes: 
//    SNMPAPI_NOERROR 
//    SNMPAPI_ERROR 
// 
// Error Codes: 
//    SNMP_MEM_ALLOC_ERROR 
//    SNMP_BERAPI_OVERFLOW 
// 
SNMPAPI 
SNMP_FUNC_TYPE SnmpUtilOidAppend( 
           OUT AsnObjectIdentifier *DestObjId, // Destination OID 
           IN AsnObjectIdentifier *SrcObjId    // Source OID 
           ) 
 
{ 
SNMPAPI nResult; 
 
 
   // Check for OID overflow 
   if ( (ULONG)DestObjId->idLength + 
        (ULONG)SrcObjId->idLength > SNMP_MAX_OID_LEN ) 
      { 
      SetLastError( SNMP_BERAPI_OVERFLOW ); 
 
      nResult = SNMPAPI_ERROR; 
      goto Exit; 
      } 
 
   // Alloc space for new object id 
   if ( NULL == 
        (DestObjId->ids = (UINT *) SnmpUtilMemReAlloc(DestObjId->ids, (sizeof(UINT) * 
                                    (SrcObjId->idLength+DestObjId->idLength)))) ) 
      { 
      SetLastError( SNMP_MEM_ALLOC_ERROR ); 
 
      nResult = SNMPAPI_ERROR; 
      goto Exit; 
      } 
 
   // Append the source to destination 
   memcpy( &DestObjId->ids[DestObjId->idLength], 
           SrcObjId->ids, SrcObjId->idLength * sizeof(UINT) ); 
 
   // Calculate length 
   DestObjId->idLength += SrcObjId->idLength; 
 
   nResult = SNMPAPI_NOERROR; 
 
Exit: 
   return nResult; 
} // SnmpUtilOidAppend 
 
 
 
// 
// SnmpUtilOidNCmp 
//    Compares two object identifiers. 
// 
// Notes: 
//    The object ids are compared from left to right (starting at the root.) 
//    At most the maximum length of OID sub-ids are compared. 
// 
// Return Codes: 
//    < 0   First parameter is 'less' than second. 
//      0   Parameters are equal 
//    > 0   First parameter is 'greater' than second. 
// 
// Error Codes: 
//    None. 
// 
SNMPAPI 
SNMP_FUNC_TYPE SnmpUtilOidNCmp( 
       IN AsnObjectIdentifier *A, // First OID 
       IN AsnObjectIdentifier *B, // Second OID 
       IN UINT Len                // Max len to compare 
       ) 
 
{ 
UINT I; 
int  nResult; 
 
 
   I       = 0; 
   nResult = 0; 
   while ( !nResult && I < min(Len, min(A->idLength, B->idLength)) ) 
      { 
      nResult = A->ids[I] - B->ids[I++]; 
      } 
 
   // Check for one being a subset of the other 
   if ( !nResult && I < Len ) 
      { 
      nResult = A->idLength - B->idLength; 
      } 
 
return nResult; 
} // SnmpUtilOidNCmp 
 
 
// 
// SnmpUtilOidCmp 
//    Compares two object identifiers. 
// 
// Notes: 
//    The object ids are compared from left to right (starting at the root.) 
// 
// Return Codes: 
//    < 0   First parameter is 'less' than second. 
//      0   Parameters are equal 
//    > 0   First parameter is 'greater' than second. 
// 
// Error Codes: 
//    None. 
// 
SNMPAPI 
SNMP_FUNC_TYPE SnmpUtilOidCmp( 
       IN AsnObjectIdentifier *A, // First OID 
       IN AsnObjectIdentifier *B  // Second OID 
       ) 
 
{ 
    return SnmpUtilOidNCmp(A,B,max(A->idLength,B->idLength)); 
 
} // SnmpUtilOidCmp 
 
 
// 
// SnmpUtilOidFree 
//    Free an Object Identifier 
// 
// Notes: 
// 
// Return Codes: 
// 
// Error Codes: 
//    None. 
// 
VOID 
SNMP_FUNC_TYPE SnmpUtilOidFree( 
        IN OUT AsnObjectIdentifier *Obj // OID to free 
        ) 
 
{ 
   SnmpUtilMemFree( Obj->ids ); 
 
   Obj->ids      = NULL; 
   Obj->idLength = 0; 
} // SnmpUtilOidFree 
 
 
 
// 
// SnmpUtilVarBindCpy 
//    Copies the variable binding. 
// 
// Notes: 
//    Does not allocate any memory for OID's or STRINGS.  Only the pointer 
//    to the storage is copied. 
// 
// Return Codes: 
//    None. 
// 
// Error Codes: 
//    None. 
// 
SNMPAPI 
SNMP_FUNC_TYPE SnmpUtilVarBindCpy( 
           RFC1157VarBind *dst, // Destination var bind 
           RFC1157VarBind *src  // Source var bind 
           ) 
 
{ 
SNMPAPI nResult; 
 
 
   // Init destination 
   dst->value.asnType = ASN_NULL; 
 
   // Copy var bind OID name 
   if ( SNMPAPI_ERROR == (nResult = SnmpUtilOidCpy(&dst->name, &src->name)) ) 
      { 
      goto Exit; 
      } 
 
   // If the value is a var bind or a string, special handling 
   switch ( src->value.asnType ) 
      { 
      case ASN_OBJECTIDENTIFIER: 
         if ( SNMPAPI_ERROR == 
              (nResult = SnmpUtilOidCpy(&dst->value.asnValue.object, 
                                     &src->value.asnValue.object)) ) 
            { 
            goto Exit; 
            } 
         break; 
 
      case ASN_RFC1155_IPADDRESS: 
      case ASN_RFC1155_OPAQUE: 
      case ASN_OCTETSTRING: 
         // Alloc storage for string 
         if ( NULL == 
              (dst->value.asnValue.string.stream = 
               SnmpUtilMemAlloc((src->value.asnValue.string.length * sizeof(BYTE)))) ) 
            { 
            SetLastError( SNMP_MEM_ALLOC_ERROR ); 
 
            nResult = SNMPAPI_ERROR; 
            goto Exit; 
            } 
 
         // Copy string 
         dst->value.asnValue.string.length = src->value.asnValue.string.length; 
         memcpy( dst->value.asnValue.string.stream, 
                 src->value.asnValue.string.stream, 
                 dst->value.asnValue.string.length ); 
         dst->value.asnValue.string.dynamic = TRUE; 
         break; 
 
      default: 
         // Copy var bind value. 
         //    This is a non-standard copy 
         dst->value = src->value; 
      } 
 
   // Set type of asn value 
   dst->value.asnType = src->value.asnType; 
 
   nResult = SNMPAPI_NOERROR; 
 
Exit: 
   if ( SNMPAPI_ERROR == nResult ) 
      { 
      SnmpUtilVarBindFree( dst ); 
      } 
 
   return nResult; 
} // SnmpUtilVarBindCpy 
 
 
 
// 
// SnmpUtilVarBindListCpy 
//    Copies the var bind list referenced by the source into the destination. 
// 
// Notes: 
//    Creates memory as needed for the list. 
// 
//    If an error occurs, memory is freed and the destination points to NULL. 
// 
// Return Codes: 
//    SNMPAPI_NOERROR 
//    SNMPAPI_ERROR 
// 
// Error Codes: 
//    SNMP_MEM_ALLOC_ERROR 
// 
SNMPAPI 
SNMP_FUNC_TYPE SnmpUtilVarBindListCpy( 
           RFC1157VarBindList *dst, // Destination var bind 
           RFC1157VarBindList *src  // Source var bind 
           ) 
 
{ 
UINT     I; 
SNMPAPI  nResult; 
 
 
   // Initialize 
   dst->len = 0; 
 
   // Alloc memory for new var bind list 
   if ( NULL == (dst->list = SnmpUtilMemAlloc((src->len * sizeof(RFC1157VarBind)))) ) 
      { 
      SetLastError( SNMP_MEM_ALLOC_ERROR ); 
 
      nResult = SNMPAPI_ERROR; 
      goto Exit; 
      } 
 
   // Copy contents of each element in list 
   for ( I=0;I < src->len;I++ ) 
      { 
      if ( SNMPAPI_ERROR == 
           (nResult = SnmpUtilVarBindCpy(&dst->list[I], &src->list[I])) ) 
         { 
         goto Exit; 
         } 
 
      // Increment successful copy count 
      dst->len++; 
      } 
 
   nResult = SNMPAPI_NOERROR; 
 
Exit: 
   if ( nResult == SNMPAPI_ERROR ) 
      { 
      SnmpUtilVarBindListFree( dst ); 
      } 
 
   return nResult; 
} // SnmpUtilVarBindListCpy 
 
 
 
// 
// SnmpUtilVarBindFree 
//    Releases memory associated with a particular variable binding. 
// 
// Notes: 
// 
// Return Codes: 
//    None. 
// 
// Error Codes: 
//    None. 
// 
VOID 
SNMP_FUNC_TYPE SnmpUtilVarBindFree( 
        RFC1157VarBind *VarBind // Variable binding to free 
        ) 
 
{ 
   // Free Var Bind name 
   SnmpUtilOidFree( &VarBind->name ); 
 
   // Free any data in the varbind value 
   switch ( VarBind->value.asnType ) 
      { 
      case ASN_OBJECTIDENTIFIER: 
         SnmpUtilOidFree( &VarBind->value.asnValue.object ); 
         break; 
 
      case ASN_RFC1155_IPADDRESS: 
      case ASN_RFC1155_OPAQUE: 
      case ASN_OCTETSTRING: 
         if ( VarBind->value.asnValue.string.dynamic == TRUE ) 
            { 
            SnmpUtilMemFree( VarBind->value.asnValue.string.stream ); 
            } 
         break; 
 
      default: 
         break; 
         // Purposefully do nothing, because no storage alloc'ed for others 
      } 
 
   // Set type to NULL 
   VarBind->value.asnType = ASN_NULL; 
} // SnmpUtilVarBindFree 
 
 
 
// 
// SnmpUtilVarBindListFree 
//    Frees any memory kept by the var binds list, including object ids that 
//    may be in the value part of the var bind. 
// 
// Notes: 
//    The calling routines do not need to call this routine if the var binds 
//    list has not been set before.  This is common sense, but just a reminder 
//    since it will be called by Release PDU and Release Trap. 
// 
//    Even if the list has length 0, the list pointer should be set to NULL, 
//    if calling this routine. 
// 
// Return Codes: 
//    None. 
// 
// Error Codes: 
//    None. 
// 
VOID 
SNMP_FUNC_TYPE SnmpUtilVarBindListFree( 
        RFC1157VarBindList *VarBindList // Variable bindings list to free 
        ) 
 
{ 
UINT I; 
 
 
   // Free items in varBinds list 
   for ( I=0;I < VarBindList->len;I++ ) 
      { 
      SnmpUtilVarBindFree( &VarBindList->list[I] ); 
      } 
 
   SnmpUtilMemFree( VarBindList->list ); 
 
   VarBindList->list = NULL; 
   VarBindList->len  = 0; 
} // SnmpUtilVarBindListFree 
 
 
#ifdef _SNMPDLL_ 
 
// 
// 
// Internal functions only after this point. 
//    The prototypes are in UTIL.H 
// 
// 
 
// 
// SnmpUtilPrintOid 
//    Display the SUBID's of an object identifier. 
// 
// Notes: 
//    This routine is responsible for allocating enough memory to contain 
//    the new identifier. 
// 
// Return Codes: 
//    SNMPAPI_NOERROR 
//    SNMPAPI_ERROR 
// 
// Error Codes: 
//    SNMP_MEM_ALLOC_ERROR 
// 
VOID  
SNMP_FUNC_TYPE SnmpUtilPrintOid( 
        IN AsnObjectIdentifier *Oid // OID to display 
        ) 
 
{ 
UINT I; 
 
 
   // Loop through OID 
   for ( I=0;I < Oid->idLength;I++ ) 
      { 
      if ( I ) 
         { 
         printf( ".%d", Oid->ids[I] ); 
         } 
      else 
         { 
         printf( "%d", Oid->ids[I] ); 
         } 
      } 
} // SnmpUtilPrintOid 
 
 
// 
// SnmpUtilPrintAsnAny 
//    Prints the value of a variable declared as type AsnAny. 
// 
// Notes: 
// 
// Return Codes: 
//    None. 
// 
// Error Codes: 
//    None. 
// 
VOID 
SNMP_FUNC_TYPE SnmpUtilPrintAsnAny( 
        IN AsnAny *Any 
        ) 
 
{ 
   switch ( Any->asnType ) 
      { 
      case ASN_INTEGER: 
         printf( "INTEGER - %ld\n", Any->asnValue.number ); 
         break; 
 
      case ASN_OCTETSTRING: 
         { 
         UINT J; 
         BOOL IsDisplayString = TRUE; 
         LPSTR StringFormat; 
 
         for ( J=0; J < Any->asnValue.string.length && IsDisplayString; J++ ) 
            { 
            IsDisplayString = isprint( Any->asnValue.string.stream[J] ); 
            } 
         StringFormat = IsDisplayString ? "%c" : "<0x%02x>" ; 
 
         printf( "OCTET STRING - " ); 
         for ( J=0; J < Any->asnValue.string.length; J++ ) 
            { 
            printf( StringFormat, Any->asnValue.string.stream[J] ); 
            } 
         putchar( '\n' ); 
         } 
         break; 
 
      case ASN_OBJECTIDENTIFIER: 
         { 
         UINT J; 
 
         printf( "OBJECT IDENTIFIER - " ); 
         for ( J=0; J < Any->asnValue.object.idLength; J++ ) 
            { 
            printf( ".%d", Any->asnValue.object.ids[J] ); 
            } 
         putchar( '\n' ); 
         } 
         break; 
 
      case ASN_NULL: 
         printf( "NULL - NULL\n" ); 
         break; 
 
      case ASN_RFC1155_IPADDRESS: 
         { 
         UINT J; 
 
         printf( "IpAddress - " ); 
         printf( "%d.%d.%d.%d ", 
            Any->asnValue.string.stream[0] , 
            Any->asnValue.string.stream[1] , 
            Any->asnValue.string.stream[2] , 
            Any->asnValue.string.stream[3] ); 
         putchar( '\n' ); 
         } 
         break; 
 
      case ASN_RFC1155_COUNTER: 
         printf( "Counter - %lu\n", Any->asnValue.number ); 
         break; 
 
      case ASN_RFC1155_GAUGE: 
         printf( "Guage - %lu\n", Any->asnValue.number ); 
         break; 
 
      case ASN_RFC1155_TIMETICKS: 
         printf( "TimeTicks - %lu\n", Any->asnValue.number ); 
         break; 
 
      case ASN_RFC1155_OPAQUE: 
         { 
         UINT J; 
 
         printf( "Opaque - " ); 
         for ( J=0; J < Any->asnValue.string.length; J++ ) 
            { 
            printf( "0x%x ", Any->asnValue.string.stream[J] ); 
            } 
         putchar( '\n' ); 
         } 
         break; 
 
      default: 
         printf( "Invalid Type\n" ); 
         } 
} // SnmpUtilPrintAsnAny 
 
 
 
// logging and debugging output routines  
 
VOID  
SNMP_FUNC_TYPE 
SnmpSvcSetLogLevel( 
        IN INT nLevel 
        ) 
{ 
    g_nLogLevel = nLevel;  
} 
 
VOID  
SNMP_FUNC_TYPE 
SnmpSvcSetLogType( 
        IN INT nOutput 
        ) 
{ 
    g_nLogType = nOutput; 
} 
 
VOID  
SNMP_FUNC_TYPE  
SnmpUtilOutput(INT nOutputType, LPSTR szBuffer) 
    { 
    static FILE *fd = NULL; 
 
    if (nOutputType & SNMP_OUTPUT_TO_CONSOLE) 
        { 
        printf("%s", szBuffer); 
        fflush(stdout); 
        } 
 
    if (nOutputType & SNMP_OUTPUT_TO_LOGFILE) 
        { 
        if (!fd) 
            { 
            fd = fopen("snmpdbg.log", "w"); 
            } 
        if (fd) 
            { 
            fprintf(fd, "%s", szBuffer); 
            fflush(fd); 
            } 
        } 
 
    if (nOutputType & SNMP_OUTPUT_TO_EVENTLOG) 
        { 
        SnmpSvcReportEvent(SNMP_EVENT_DEBUG_TRACE, 1, &szBuffer, NO_ERROR); 
        } 
 
    if (nOutputType & SNMP_OUTPUT_TO_DEBUGGER) 
        { 
        OutputDebugString(szBuffer); 
        } 
 
    }  
 
VOID  
SNMP_FUNC_TYPE  
SnmpUtilDbgPrint(INT nLevel, LPSTR szFormat, ...) 
    { 
    va_list arglist; 
    char szBuffer[MAX_DEBUG_LEN]; 
 
    if (nLevel <= g_nLogLevel) 
        { 
        va_start(arglist, szFormat); 
 
        vsprintf(szBuffer, szFormat, arglist); 
 
        SnmpUtilOutput(g_nLogType, szBuffer); 
        } 
    } 
 
LPSTR 
SNMP_FUNC_TYPE 
SnmpUtilOidToA(AsnObjectIdentifier *Oid) 
    { 
    return SnmpUtilIdsToA(Oid->ids, Oid->idLength);  
    }  
 
LPSTR 
SNMP_FUNC_TYPE 
SnmpUtilIdsToA(UINT *Oid, UINT OidLen) 
    { 
    UINT I; 
    UINT J; 
    static char szBuffer[MAX_DEBUG_LEN]; 
 
    if (OidLen) 
       { 
       J = sprintf(szBuffer, "%d", Oid[0]); 
 
       for ( I=1;I < OidLen;I++ ) 
          { 
          J += sprintf(&szBuffer[J], ".%d", Oid[I]); 
          } 
       } 
    else 
       { 
       sprintf(szBuffer, "NUL"); 
       } 
 
    return szBuffer; 
    }  
 
VOID  
SNMP_FUNC_TYPE 
SnmpSvcReportEvent(DWORD nMsgId, DWORD cSubStrings, LPSTR *SubStrings, DWORD nErrorCode) 
    { 
    HANDLE lh; 
    WORD wEventType; 
    LPVOID lpData; 
    WORD cbData; 
 
    // determine type of event from message id.  note that 
    // all debug messages regardless of their severity are 
    // listed under SNMP_EVENT_DEBUG_TRACE (informational).   
    // see evtlog.h for the entire list of event messages. 
    switch ( nMsgId >> 30 ) 
        { 
        case STATUS_SEVERITY_INFORMATIONAL: 
        case STATUS_SEVERITY_SUCCESS: 
            wEventType = EVENTLOG_INFORMATION_TYPE; 
            break; 
        case STATUS_SEVERITY_WARNING: 
            wEventType = EVENTLOG_WARNING_TYPE; 
            break; 
        case STATUS_SEVERITY_ERROR: 
        default: 
            wEventType = EVENTLOG_ERROR_TYPE; 
            break; 
        } 
 
    cbData = (nErrorCode == NO_ERROR) ? 0 : sizeof(DWORD); 
    lpData = (nErrorCode == NO_ERROR) ? NULL : &nErrorCode; 
 
    if (lh = RegisterEventSource(NULL, "SNMP")) 
        { 
        ReportEvent( 
           lh,              
           wEventType,      
           0,                  // event category 
           nMsgId,          
           NULL,               // user sids 
           (WORD)cSubStrings,     
           cbData,               
           SubStrings,      
           lpData); 
         
        DeregisterEventSource(lh); 
        } 
    } 
 
#endif // _SNMPDLL_ 
 
VOID 
SNMP_FUNC_TYPE SnmpUtilMemFree( 
    IN void *x 
    ) 
{ 
    if (x != NULL) { 
 
#if defined(DBG) && defined(_SNMPDLL_) 
 
        g_nBytesTotal -= GlobalSize(x); 
 
        SNMPDBG(( 
            SNMP_LOG_VERBOSE, 
            "SNMP: MEM: releasing 0x%08lx (%d bytes, %d total).\n", 
            x, GlobalSize(x), g_nBytesTotal 
            )); 
 
#endif 
 
        GlobalFree( (HGLOBAL) x ); 
    } 
 
    return; 
} 
 
LPVOID 
SNMP_FUNC_TYPE SnmpUtilMemAlloc( 
    IN unsigned int x 
    ) 
{ 
    void *addr; 
    addr = GlobalAlloc( GMEM_FIXED | GMEM_ZEROINIT, (DWORD)x ); 
 
#if defined(DBG) && defined(_SNMPDLL_) 
 
    g_nBytesTotal += (addr ? GlobalSize(addr) : 0); 
 
    SNMPDBG(( 
        SNMP_LOG_VERBOSE, 
        "SNMP: MEM: allocated 0x%08lx (%d bytes, %d total).\n", 
        addr, addr ? GlobalSize(addr) : 0, g_nBytesTotal 
        )); 
 
#endif 
 
    return(addr); 
} 
 
LPVOID 
SNMP_FUNC_TYPE SnmpUtilMemReAlloc( 
    IN void *x, 
    IN unsigned int y 
    ) 
{ 
    void *addr; 
 
    if (x == NULL) { 
 
        addr = SnmpUtilMemAlloc( y ); 
 
    } else { 
 
#if defined(DBG) && defined(_SNMPDLL_) 
 
        SNMPDBG(( 
            SNMP_LOG_VERBOSE, 
            "SNMP: MEM: expanding 0x%08lx (%d bytes) to %d bytes.\n", 
            x, GlobalSize(x), y 
            )); 
 
        g_nBytesTotal -= GlobalSize(x); 
 
#endif 
 
        addr = GlobalReAlloc( (HGLOBAL) x, (DWORD)y, GMEM_MOVEABLE | GMEM_ZEROINIT); 
 
#if defined(DBG) && defined(_SNMPDLL_) 
 
        g_nBytesTotal += (addr ? GlobalSize(addr) : 0); 
 
        SNMPDBG(( 
            SNMP_LOG_VERBOSE, 
            "SNMP: MEM: allocated 0x%08lx (%d bytes, %d total).\n", 
            addr, addr ? GlobalSize(addr) : 0, g_nBytesTotal 
            )); 
 
#endif 
 
    } 
     
    return(addr); 
} 
 
 
#ifdef _SNMPDLL_ 
 
// return true if the string contains only hex digits 
 
BOOL isHex(LPSTR str, int strLen) 
    { 
    int ii; 
 
    for (ii=0; ii < strLen; ii++) 
        if (isxdigit(*str)) 
            str++; 
        else 
            return FALSE; 
 
    return TRUE; 
    } 
 
unsigned int toHex(unsigned char x) 
    { 
    if (x >= '0' && x <= '9') 
        return x - '0'; 
    else if (x >= 'A' && x <= 'F') 
        return x - 'A' + 10; 
    else if (x >= 'a' && x <= 'f') 
        return x - 'a' + 10; 
    else 
        return 0; 
    } 
 
// convert str to hex number of NumDigits (must be even) into pNum 
void atohex(IN LPSTR str, IN int NumDigits, OUT unsigned char *pNum) 
    { 
    int i, j; 
 
    j=0; 
    for (i=0; i < (NumDigits>>1) ; i++) 
        { 
        pNum[i] = (toHex(str[j]) << 4) + toHex(str[j+1]); 
        j+=2; 
        } 
    } 
 
 
 
// return true if addrText is of the form 123456789ABC or 
// 000001.123456789abc 
// if pNetNum is not null, upon successful return, pNetNum = network number 
// if pNodeNum is not null, upon successful return, pNodeNum = node number 
 
BOOL  
SNMP_FUNC_TYPE  
SnmpSvcAddrIsIpx( 
    IN  LPSTR addrText, 
    OUT char pNetNum[4], 
    OUT char pNodeNum[6]) 
    { 
    int addrTextLen; 
 
    addrTextLen = strlen(addrText); 
    if (addrTextLen == 12 && isHex(addrText, 12)) 
        { 
            if (pNetNum) 
                *((UNALIGNED unsigned long *) pNetNum) = 0L; 
            if (pNodeNum) 
                atohex(addrText, 12, pNodeNum); 
            return TRUE; 
        } 
    else if (addrTextLen == 21 && addrText[8] == '.' && isHex(addrText, 8) && 
            isHex(addrText+9, 12)) 
        { 
            if (pNetNum) 
                atohex(addrText, 8, pNetNum); 
            if (pNodeNum) 
                atohex(addrText+9, 12, pNodeNum); 
            return TRUE; 
        } 
    else 
        return FALSE; 
    } 
 
BOOL  
SNMP_FUNC_TYPE 
SnmpSvcAddrToSocket( 
    LPSTR addrText, 
    struct sockaddr *addrEncoding) 
    { 
 
// --------- BEGIN: PROTOCOL SPECIFIC SOCKET CODE BEGIN... --------- 
 
    SOCKADDR_IPX mgrAddr_ipx; 
 
    if (SnmpSvcAddrIsIpx(addrText, mgrAddr_ipx.sa_netnum, mgrAddr_ipx.sa_nodenum)) 
        { 
        // currently, we don't/can't do gethostbyname on IPX, so no IPX 
        // host name allowed. 
        mgrAddr_ipx.sa_family = AF_IPX; 
        bcopy(&mgrAddr_ipx, addrEncoding, sizeof(mgrAddr_ipx)); 
        } 
    else        // if not IPX, must be INET 
        { 
        struct hostent *hp; 
        unsigned long addr; 
        struct sockaddr_in mgrAddr_in; 
 
        if ((long)(addr = inet_addr(addrText)) == -1) 
            { 
            if ((hp = gethostbyname(addrText)) == NULL) 
                { 
                return FALSE; 
                } 
            else 
                { 
                bcopy((char *)hp->h_addr, (char *)&mgrAddr_in.sin_addr, 
                      sizeof(unsigned long)); 
                } 
            } 
        else 
            { 
            bcopy((char *)&addr, (char *)&mgrAddr_in.sin_addr, 
                  sizeof(unsigned long)); 
            } 
 
        mgrAddr_in.sin_family = AF_INET; 
        mgrAddr_in.sin_port = htons(WKSN_UDP_TRAP); 
        bcopy(&mgrAddr_in, addrEncoding, sizeof(mgrAddr_in)); 
        } 
 
// --------- END: PROTOCOL SPECIFIC SOCKET CODE END. --------------- 
 
    return TRUE; 
    } // end SnmpSvcAddrToSocket() 
 
 
AsnObjectIdentifier * 
SNMP_FUNC_TYPE 
SnmpSvcGetEnterpriseOID( 
    ) 
{ 
    // just return oid 
    return g_enterprise; 
} 
 
#endif // _SNMPDLL_ 
 
//-------------------------------- END --------------------------------------