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


/*++ 
 
Copyright (c) 1992-1996  Microsoft Corporation 
 
Module Name: 
 
    pduapi.c 
 
Abstract: 
 
    Performs all functions to encode/decode a RFC 1157 PDU and trap. 
 
Environment: 
 
    User Mode - Win32 
 
Revision History: 
 
    10-May-1996 DonRyan 
        Removed banner from Technology Dynamics, Inc. 
 
--*/ 
 
//--------------------------- WINDOWS DEPENDENCIES -------------------------- 
 
//--------------------------- STANDARD DEPENDENCIES -- #include ---- 
 
#include  
 
//--------------------------- MODULE DEPENDENCIES -- #include"xxxxx.h" ------ 
 
#include  
#include  
 
#include "berapi.h" 
 
//--------------------------- SELF-DEPENDENCY -- ONE #include"module.h" ----- 
 
#include "pduapi.h" 
 
//--------------------------- PUBLIC VARIABLES --(same as in module.h file)-- 
 
//--------------------------- PRIVATE CONSTANTS ----------------------------- 
 
#define PDU_ERRORSTATUS_LAST   SNMP_ERRORSTATUS_GENERR 
#define PDU_GENERICTRAP_LAST   SNMP_GENERICTRAP_ENTERSPECIFIC 
 
//--------------------------- PRIVATE STRUCTS ------------------------------- 
 
//--------------------------- PRIVATE VARIABLES ----------------------------- 
 
//--------------------------- PRIVATE PROTOTYPES ---------------------------- 
 
void PDU_ReleasePDU( 
        RFC1157Pdu *pdu // PDU to release 
        ); 
 
void PDU_ReleaseTrap( 
        RFC1157TrapPdu *pdu // Trap to release 
	); 
 
//--------------------------- PRIVATE PROCEDURES ---------------------------- 
 
//--------------------------- PUBLIC PROCEDURES ----------------------------- 
 
// 
// SnmpPduEncodePdu: 
//    Encode a RFC1157 PDU. 
// 
// Notes: 
//    The encoded PDU is left in reverse order so the rest of the message 
//    information can be appended to the buffer, and then reversed. 
// 
//    The buffer information must be initialized prior to calling this routine. 
// 
//    If an error occurs, the entire buffer is freed, and set to NULL. 
// 
// Return Codes: 
//    SNMPAPI_NOERROR 
//    SNMPAPI_ERROR 
// 
// Error Codes: 
//    SNMP_PDUAPI_INVALID_ES 
// 
SNMPAPI SnmpPduEncodePdu( 
	   IN BYTE nType,         // Type of RFC 1157 PDU to encode 
           IN RFC1157Pdu *pdu,    // RFC 1157 PDU to encode into stream buffer 
           IN OUT BYTE **pBuffer, // Stream buffer to accept encoding 
	   IN OUT UINT *nLength   // Length of stream buffer 
	   ) 
 
{ 
SNMPAPI  nResult; 
UINT     nBufStart; 
int      I; 
 
 
   // Check for valid error status 
   if ( pdu->errorStatus > PDU_ERRORSTATUS_LAST ) 
      { 
      SetLastError( SNMP_PDUAPI_INVALID_ES ); 
      nResult = SNMPAPI_ERROR; 
 
      goto Exit; 
      } 
 
   // Save start position of buffer 
   nBufStart = *nLength; 
 
   // Encode var binds 
   for ( I=pdu->varBinds.len-1;I >= 0;I-- ) 
      { 
      UINT nSeqStart; 
 
 
      // Save starting point of sequence 
      nSeqStart = *nLength; 
 
      // Encode variable value 
      if ( SNMPAPI_ERROR == 
           SnmpBerEncodeAsnAny(&pdu->varBinds.list[I].value, 
	                       pBuffer, nLength) ) 
         { 
	 goto Exit; 
	 } 
 
      // Encode variable name 
      if ( SNMPAPI_ERROR == 
           SnmpBerEncodeAsnObjectId(ASN_OBJECTIDENTIFIER, 
                                    &pdu->varBinds.list[I].name, 
	                            pBuffer, nLength) ) 
         { 
	 goto Exit; 
	 } 
 
      // Encode the entire variable info. as a sequence 
      if ( SNMPAPI_ERROR == 
           SnmpBerEncodeAsnSequence(*nLength - nSeqStart, 
	                            pBuffer, nLength) ) 
         { 
	 goto Exit; 
	 } 
      } 
 
   // Encode the var bind list as a sequence of 'sequence's 
   if ( SNMPAPI_ERROR == 
        SnmpBerEncodeAsnImplicitSeq(ASN_SEQUENCEOF, *nLength - nBufStart, 
                                    pBuffer, nLength) ) 
      { 
      goto Exit; 
      } 
 
   // Encode error-index 
   if ( SNMPAPI_ERROR == 
        (nResult = SnmpBerEncodeAsnInteger(ASN_INTEGER, 
	                                   pdu->errorIndex, 
                                           pBuffer, nLength)) ) 
      { 
      goto Exit; 
      } 
 
   // Encode error-status 
   if ( SNMPAPI_ERROR == 
        (nResult = SnmpBerEncodeAsnInteger(ASN_INTEGER, 
	                                   pdu->errorStatus, 
                                           pBuffer, nLength)) ) 
      { 
      goto Exit; 
      } 
 
   // Encode request-id 
   if ( SNMPAPI_ERROR == 
        (nResult = SnmpBerEncodeAsnInteger(ASN_INTEGER, 
	                                   pdu->requestId, 
                                           pBuffer, nLength)) ) 
      { 
      goto Exit; 
      } 
 
   // Encode entire pdu as Implicit Sequence 
   if ( SNMPAPI_ERROR == 
        (nResult = SnmpBerEncodeAsnImplicitSeq(nType, *nLength - nBufStart, 
                                               pBuffer, nLength)) ) 
      { 
      goto Exit; 
      } 
 
Exit: 
   if ( nResult == SNMPAPI_ERROR ) 
      { 
      SnmpUtilMemFree( *pBuffer ); 
 
      *pBuffer = NULL; 
      *nLength = 0; 
      } 
 
   return nResult; 
} // SnmpPduEncodePdu 
 
 
 
// 
// SnmpPduDecodePdu 
//    Decode a PDU. 
// 
// Notes: 
// 
// Return Codes: 
//    SNMPAPI_NOERROR 
//    SNMPAPI_ERROR 
// 
// Error Codes: 
//    SNMP_MEM_ALLOC_ERROR 
//    SNMP_PDUAPI_INVALID_ES 
// 
SNMPAPI SnmpPduDecodePdu( 
           IN BYTE nType,         // Type of RFC 1157 PDU to decode 
           OUT RFC1157Pdu *pdu,   // RFC 1157 PDU to accept decoding 
           IN OUT BYTE **pBuffer, // Stream buffer to decode 
	   IN OUT UINT *nLength   // Length of stream buffer 
	   ) 
 
{ 
UINT    BufLen; 
BYTE    *BufPtr; 
AsnAny  pResult; 
SNMPAPI nResult; 
 
 
    // Initialize variable bindings' list 
    pdu->varBinds.list = NULL; 
    pdu->varBinds.len  = 0; 
 
    //   process the sequence encapsuling the PDU 
    if ( SNMPAPI_ERROR == 
         (nResult = SnmpBerDecodeAsnStream(nType, pBuffer, nLength, &pResult)) ) 
       { 
       goto Exit; 
       } 
 
    // Make copy of sequence information 
    BufPtr = pResult.asnValue.sequence.stream; 
    BufLen = pResult.asnValue.sequence.length; 
 
    // Decode request-id 
    if ( SNMPAPI_ERROR == 
         (nResult = SnmpBerDecodeAsnStream(ASN_INTEGER, &BufPtr, 
                                           &BufLen, &pResult)) ) 
       { 
       goto Exit; 
       } 
 
    // Save request-id 
    pdu->requestId = pResult.asnValue.number; 
 
    // Decode error-status 
    if ( SNMPAPI_ERROR == 
         (nResult = SnmpBerDecodeAsnStream(ASN_INTEGER, &BufPtr, 
                                           &BufLen, &pResult)) ) 
       { 
       goto Exit; 
       } 
 
    // Save error-status 
    pdu->errorStatus = pResult.asnValue.number; 
 
   // Check for valid error status 
   if ( pdu->errorStatus > PDU_ERRORSTATUS_LAST ) 
      { 
      SetLastError( SNMP_PDUAPI_INVALID_ES ); 
      nResult = SNMPAPI_ERROR; 
 
      goto Exit; 
      } 
 
    // Decode error-index 
    if ( SNMPAPI_ERROR == 
         (nResult = SnmpBerDecodeAsnStream(ASN_INTEGER, &BufPtr, 
                                           &BufLen, &pResult)) ) 
       { 
       goto Exit; 
       } 
 
    // Save error-status 
    pdu->errorIndex = pResult.asnValue.number; 
 
    // Decode variable-bindings' sequence 
    if ( SNMPAPI_ERROR == 
         (nResult = SnmpBerDecodeAsnStream(ASN_SEQUENCEOF, &BufPtr, 
                                           &BufLen, &pResult)) ) 
       { 
       goto Exit; 
       } 
 
    // Make temps of sequence data 
    BufLen = pResult.asnValue.sequence.length; 
    BufPtr = pResult.asnValue.sequence.stream; 
 
    // Gather variables and save in pdu list 
    while ( BufLen ) 
       { 
       BYTE           *VarBufPtr; 
       UINT           VarBufLen; 
 
 
       // Alloc space for variable binding 
       pdu->varBinds.list = (RFC1157VarBind *) SnmpUtilMemReAlloc( pdu->varBinds.list, 
                            ((pdu->varBinds.len+1)*sizeof(RFC1157VarBind)) ); 
 
       // Check for errors on alloc 
       if ( pdu->varBinds.list == NULL ) 
          { 
          SetLastError( SNMP_MEM_ALLOC_ERROR ); 
 
          nResult = SNMPAPI_ERROR; 
          goto Exit; 
          } 
 
       // Decode sequence of info 
       if ( SNMPAPI_ERROR == 
            (nResult = SnmpBerDecodeAsnStream(ASN_SEQUENCE, 
                                              &BufPtr, &BufLen, &pResult)) ) 
          { 
          goto Exit; 
          } 
 
       // Setup variable bindings' buffer 
       VarBufPtr = pResult.asnValue.sequence.stream; 
       VarBufLen = pResult.asnValue.sequence.length; 
 
       // Decode name 
       if ( SNMPAPI_ERROR == 
            (nResult = SnmpBerDecodeAsnStream(ASN_OBJECTIDENTIFIER, &VarBufPtr, 
                                              &VarBufLen, &pResult)) ) 
          { 
          goto Exit; 
          } 
 
       // Save name of variable 
       //    This is a non-standard copy - MS C specific 
       pdu->varBinds.list[pdu->varBinds.len].name = pResult.asnValue.object; 
 
       // Get ASN Type 
       if ( SNMPAPI_ERROR == 
            (nResult = SnmpBerQueryAsnType(VarBufPtr, VarBufLen)) ) 
	  { 
	  goto Exit; 
	  } 
 
       // Decode value 
       if ( SNMPAPI_ERROR == 
            (nResult = SnmpBerDecodeAsnStream( (BYTE)nResult, 
                              &VarBufPtr, &VarBufLen, 
	                      &pdu->varBinds.list[pdu->varBinds.len++].value)) ) 
          { 
          goto Exit; 
          } 
       } 
 
Exit: 
   if ( nResult == SNMPAPI_ERROR ) 
      { 
      PDU_ReleasePDU( pdu ); 
      } 
 
   return nResult; 
} // SnmpPduDecodePdu 
 
 
 
// 
// SnmpPduEncodeTrap: 
//    The encoded TRAP is left in reverse order so the rest of the message 
//    information can be appended to the buffer, and then reversed. 
// 
// Notes: 
//    The buffer information must be initialized prior to calling this routine. 
// 
//    If an error occurs, the entire buffer is freed and set to NULL. 
// 
// Return Codes: 
//    SNMPAPI_NOERROR 
//    SNMPAPI_ERROR 
// 
// Error Codes: 
//    SNMP_PDUAPI_INVALID_GT 
// 
SNMPAPI SnmpPduEncodeTrap( 
	   IN BYTE nType,          // Type of RFC 1157 TRAP to encode 
           IN RFC1157TrapPdu *pdu, // RFC 1157 Trap to encode into stream buffer 
           IN OUT BYTE **pBuffer,  // Stream buffer to accept encoding 
	   IN OUT UINT *nLength    // Length of stream buffer 
	   ) 
 
{ 
SNMPAPI  nResult; 
UINT     nBufStart; 
int      I; 
 
 
   // Check for valid generic trap 
   if ( pdu->genericTrap > PDU_GENERICTRAP_LAST ) 
      { 
      SetLastError( SNMP_PDUAPI_INVALID_GT ); 
      nResult = SNMPAPI_ERROR; 
 
      goto Exit; 
      } 
 
   // Save start position of buffer 
   nBufStart = *nLength; 
 
   // Encode var binds 
   for( I=pdu->varBinds.len-1;I >= 0;I-- ) 
      { 
      UINT nSeqStart; 
 
 
      // Save starting point of sequence 
      nSeqStart = *nLength; 
 
      // Encode variable value 
      if ( SNMPAPI_ERROR == 
           SnmpBerEncodeAsnAny(&pdu->varBinds.list[I].value, 
	                       pBuffer, nLength) ) 
         { 
	 goto Exit; 
	 } 
 
      // Encode variable name 
      if ( SNMPAPI_ERROR == 
           SnmpBerEncodeAsnObjectId(ASN_OBJECTIDENTIFIER, 
                                    &pdu->varBinds.list[I].name, 
	                            pBuffer, nLength) ) 
         { 
	 goto Exit; 
	 } 
 
      // Encode the entire variable info. as a sequence 
      if ( SNMPAPI_ERROR == 
           SnmpBerEncodeAsnSequence(*nLength - nSeqStart, 
	                            pBuffer, nLength) ) 
         { 
	 goto Exit; 
	 } 
      } 
 
   // Encode the var bind list as a sequence of 'sequence's 
      if ( SNMPAPI_ERROR == 
           SnmpBerEncodeAsnImplicitSeq(ASN_SEQUENCEOF, *nLength - nBufStart, 
	                               pBuffer, nLength) ) 
         { 
	 goto Exit; 
	 } 
 
   // Encode time-stamp 
   if ( SNMPAPI_ERROR == 
        (nResult = SnmpBerEncodeAsnInteger(ASN_RFC1155_TIMETICKS, 
                                           pdu->timeStamp, 
                                           pBuffer, nLength)) ) 
      { 
      goto Exit; 
      } 
 
   // Encode specific-trap 
   if ( SNMPAPI_ERROR == 
        (nResult = SnmpBerEncodeAsnInteger(ASN_INTEGER, 
                                           pdu->specificTrap, 
                                           pBuffer, nLength)) ) 
      { 
      goto Exit; 
      } 
 
   // Encode generic-trap 
   if ( SNMPAPI_ERROR == 
        (nResult = SnmpBerEncodeAsnInteger(ASN_INTEGER, 
                                           pdu->genericTrap, 
                                           pBuffer, nLength)) ) 
      { 
      goto Exit; 
      } 
 
   // Encode agent-addr 
   if ( SNMPAPI_ERROR == 
        (nResult = SnmpBerEncodeAsnOctetStr(ASN_RFC1155_IPADDRESS, 
                                            &pdu->agentAddr, 
                                            pBuffer, nLength)) ) 
      { 
      goto Exit; 
      } 
 
   // Encode enterprise 
   if ( SNMPAPI_ERROR == 
        (nResult = SnmpBerEncodeAsnObjectId(ASN_OBJECTIDENTIFIER, 
                                            &pdu->enterprise, 
                                            pBuffer, nLength)) ) 
      { 
      goto Exit; 
      } 
 
   // Encode entire pdu as Implicit Sequence 
   if ( SNMPAPI_ERROR == 
        (nResult = SnmpBerEncodeAsnImplicitSeq(nType, 
	                                       *nLength - nBufStart, 
                                               pBuffer, nLength)) ) 
      { 
      goto Exit; 
      } 
 
Exit: 
   if ( nResult == SNMPAPI_ERROR ) 
      { 
      SnmpUtilMemFree( *pBuffer ); 
 
      *pBuffer = NULL; 
      *nLength = 0; 
      } 
 
   return nResult; 
} // SnmpPduEncodeTrap 
 
 
 
// 
// SnmpPduDecodeTrap: 
//   Decode a TRAP. 
// 
// Notes: 
// 
// Return Codes: 
//    SNMPAPI_NOERROR 
//    SNMPAPI_ERROR 
// 
// Error Codes: 
//    SNMP_MEM_ALLOC_ERROR 
//    SNMP_PDUAPI_INVALID_GT 
// 
SNMPAPI SnmpPduDecodeTrap( 
	   IN BYTE nType,           // Type of RFC 1157 TRAP to decode 
           OUT RFC1157TrapPdu *pdu, // RFC 1157 Trap to accept decoding 
           IN OUT BYTE **pBuffer,   // Stream buffer to decode 
	   IN OUT UINT *nLength     // Length of stream buffer 
	   ) 
 
{ 
UINT    BufLen; 
BYTE    *BufPtr; 
AsnAny  pResult; 
SNMPAPI nResult; 
 
 
    // Initialize variable bindings' list 
    pdu->enterprise.ids = NULL; 
    pdu->varBinds.list  = NULL; 
    pdu->varBinds.len   = 0; 
 
    //   process the sequence encapsuling the PDU 
    if ( SNMPAPI_ERROR == 
         (nResult = SnmpBerDecodeAsnStream(nType, pBuffer, nLength, &pResult)) ) 
       { 
       goto Exit; 
       } 
 
    // Make copy of sequence information 
    BufPtr = pResult.asnValue.sequence.stream; 
    BufLen = pResult.asnValue.sequence.length; 
 
    // Decode enterprise 
    if ( SNMPAPI_ERROR == 
         (nResult = SnmpBerDecodeAsnStream(ASN_OBJECTIDENTIFIER, &BufPtr, 
                                           &BufLen, &pResult)) ) 
       { 
       goto Exit; 
       } 
 
   // This is a non-standard structure copy 
   pdu->enterprise = pResult.asnValue.object; 
 
    // Decode agent-addr 
    if ( SNMPAPI_ERROR == 
         (nResult = SnmpBerDecodeAsnStream(ASN_RFC1155_IPADDRESS, &BufPtr, 
                                           &BufLen, &pResult)) ) 
       { 
       goto Exit; 
       } 
 
   // This is a non-standard structure copy 
   pdu->agentAddr = pResult.asnValue.string; 
 
   // Decode generic-trap 
   if ( SNMPAPI_ERROR == 
        (nResult = SnmpBerDecodeAsnStream(ASN_INTEGER, &BufPtr, 
                                          &BufLen, &pResult)) ) 
      { 
      goto Exit; 
      } 
 
    pdu->genericTrap = pResult.asnValue.number; 
 
   // Check for valid generic trap 
   if ( pdu->genericTrap > PDU_GENERICTRAP_LAST ) 
      { 
      SetLastError( SNMP_PDUAPI_INVALID_GT ); 
      nResult = SNMPAPI_ERROR; 
 
      goto Exit; 
      } 
 
    // Decode specific-trap 
    if ( SNMPAPI_ERROR == 
         (nResult = SnmpBerDecodeAsnStream(ASN_INTEGER, &BufPtr, 
                                           &BufLen, &pResult)) ) 
       { 
       goto Exit; 
       } 
 
    pdu->specificTrap = pResult.asnValue.number; 
 
    // Decode time-stamp 
    if ( SNMPAPI_ERROR == 
         (nResult = SnmpBerDecodeAsnStream(ASN_RFC1155_TIMETICKS, &BufPtr, 
                                           &BufLen, &pResult)) ) 
       { 
       goto Exit; 
       } 
 
    pdu->timeStamp = pResult.asnValue.number; 
 
    // Decode variable-bindings' sequence 
    if ( SNMPAPI_ERROR == 
         (nResult = SnmpBerDecodeAsnStream(ASN_SEQUENCEOF, &BufPtr, 
                                           &BufLen, &pResult)) ) 
       { 
       goto Exit; 
       } 
 
    // Make temps of sequence data 
    BufLen = pResult.asnValue.sequence.length; 
    BufPtr = pResult.asnValue.sequence.stream; 
 
    // Gather variables and save in pdu list 
    while ( BufLen ) 
       { 
       BYTE           *VarBufPtr; 
       UINT           VarBufLen; 
 
 
       // Alloc space for variable binding 
       pdu->varBinds.list = (RFC1157VarBind *) SnmpUtilMemReAlloc( pdu->varBinds.list, 
                            ((pdu->varBinds.len+1)*sizeof(RFC1157VarBind)) ); 
 
       // Check for errors on alloc 
       if ( pdu->varBinds.list == NULL ) 
          { 
          SetLastError( SNMP_MEM_ALLOC_ERROR ); 
 
          nResult = SNMPAPI_ERROR; 
          goto Exit; 
          } 
 
       // Decode sequence of info 
       if ( SNMPAPI_ERROR == 
            (nResult = SnmpBerDecodeAsnStream(ASN_SEQUENCE, 
                                              &BufPtr, &BufLen, &pResult)) ) 
          { 
          goto Exit; 
          } 
 
       // Setup variable bindings' buffer 
       VarBufPtr = pResult.asnValue.sequence.stream; 
       VarBufLen = pResult.asnValue.sequence.length; 
 
       // Decode name 
       if ( SNMPAPI_ERROR == 
            (nResult = SnmpBerDecodeAsnStream(ASN_OBJECTIDENTIFIER, &VarBufPtr, 
                                              &VarBufLen, &pResult)) ) 
          { 
          goto Exit; 
          } 
 
       // Save name of variable 
       //    This is a non-standard copy - MS C specific 
       pdu->varBinds.list[pdu->varBinds.len].name = pResult.asnValue.object; 
 
       // Decode value 
       if ( SNMPAPI_ERROR == 
            (nResult = SnmpBerDecodeAsnStream( 
                              (BYTE)SnmpBerQueryAsnType(VarBufPtr, VarBufLen), 
                              &VarBufPtr, &VarBufLen, 
	                      &pdu->varBinds.list[pdu->varBinds.len++].value)) ) 
          { 
          goto Exit; 
          } 
       } 
 
Exit: 
   if ( nResult == SNMPAPI_ERROR ) 
      { 
      PDU_ReleaseTrap( pdu ); 
      } 
 
   return nResult; 
} // SnmpPduDecodePdu 
 
 
 
// 
// SnmpPduEncodeAnyPdu 
//    Determines the type of PDU to encode (PDU or TRAP) and calls the 
//    appropriate routine to do it. 
// 
// Notes: 
//    If the pdu type is unrecognized, this is an error and the buffer info. 
//    is freed. 
// 
// Return Codes: 
//    SNMPAPI_NOERROR 
//    SNMPAPI_ERROR 
// 
// Error Codes: 
//    SNMP_PDUAPI_UNRECOGNIZED_PDU 
// 
SNMPAPI SnmpPduEncodeAnyPdu( 
           RFC1157Pdus *pdu,      // PDU/TRAP to Encode 
	   IN OUT BYTE **pBuffer, // Buffer to accept encoding 
	   IN OUT UINT *nLength   // Length of buffer 
	   ) 
 
{ 
SNMPAPI nResult; 
 
 
    // Encode PDU/TRAP 
    switch ( pdu->pduType ) 
        { 
	case ASN_RFC1157_GETREQUEST: 
	case ASN_RFC1157_GETNEXTREQUEST: 
	case ASN_RFC1157_GETRESPONSE: 
	case ASN_RFC1157_SETREQUEST: 
            nResult = SnmpPduEncodePdu( pdu->pduType, &pdu->pduValue.pdu, 
	                                pBuffer, nLength ); 
            break; 
 
	case ASN_RFC1157_TRAP: 
            nResult = SnmpPduEncodeTrap( pdu->pduType, &pdu->pduValue.trap, 
	                                 pBuffer, nLength ); 
            break; 
 
        default: 
	    SetLastError( SNMP_PDUAPI_UNRECOGNIZED_PDU ); 
 
            nResult = SNMPAPI_ERROR; 
        } 
 
   if ( nResult == SNMPAPI_ERROR ) 
      { 
      SnmpUtilMemFree( *pBuffer ); 
 
      *pBuffer = NULL; 
      *nLength = 0; 
      } 
 
   return nResult; 
} // SnmpPduEncodeAnyPdu 
 
 
 
// 
// SnmpPduDecodeAnyPdu 
//    Determines and sets the type of PDU to decode (PDU or TRAP) and calls the 
//    appropriate routine to do it. 
// 
// Notes: 
// 
// Return Codes: 
//    SNMPAPI_NOERROR 
//    SNMPAPI_ERROR 
// 
// Error Codes: 
//    SNMP_PDUAPI_UNRECOGNIZED_PDU 
// 
SNMPAPI SnmpPduDecodeAnyPdu( 
	   OUT RFC1157Pdus *pdu,  // Will accept PDU or TRAP as result 
           IN OUT BYTE **pBuffer, // Stream buffer to decode 
	   IN OUT UINT *nLength   // Length of stream buffer 
	   ) 
 
{ 
SNMPAPI nResult; 
 
 
   // Get pdu type 
   if ( SNMPAPI_ERROR == 
        (pdu->pduType = (BYTE)(nResult = SnmpBerQueryAsnType(*pBuffer, *nLength))) ) 
      { 
      goto Exit; 
      } 
 
   switch ( nResult ) 
      { 
      case ASN_RFC1157_GETREQUEST: 
      case ASN_RFC1157_GETNEXTREQUEST: 
      case ASN_RFC1157_GETRESPONSE: 
      case ASN_RFC1157_SETREQUEST: 
         nResult = SnmpPduDecodePdu( pdu->pduType, &pdu->pduValue.pdu, 
	                             pBuffer, nLength ); 
         break; 
 
      case ASN_RFC1157_TRAP: 
         nResult = SnmpPduDecodeTrap( pdu->pduType, &pdu->pduValue.trap, 
				      pBuffer, nLength ); 
         break; 
 
      default: 
	 SetLastError( SNMP_PDUAPI_UNRECOGNIZED_PDU ); 
 
         nResult = SNMPAPI_ERROR; 
      } 
 
Exit: 
   return nResult; 
} // SnmpPduDecodeAnyPdu 
 
 
 
// 
// PDU_ReleasePDU 
//    Frees all memory associated with a pdu, including a call to 
//    SnmpUtilVarBindListFree to free the var binds list. 
// 
// Notes: 
//    The dynamic memory associated with a pdu must be set before calling 
//    this routine. 
// 
// Return Codes: 
//    None. 
// 
// Error Codes: 
//    None. 
// 
void PDU_ReleasePDU( 
        RFC1157Pdu *pdu // PDU to release 
        ) 
 
{ 
   SnmpUtilVarBindListFree( &pdu->varBinds ); 
} // PDU_ReleasePDU 
 
 
 
// 
// PDU_ReleaseTrap 
//    Frees all memory associated with a trap, including a call to 
//    SnmpUtilVarBindListFree to free the var binds list. 
// 
// Notes: 
//    The dynamic memory associated with a trap pdu must be set before calling 
//    this routine. 
// 
// Return Codes: 
//    None. 
// 
// Error Codes: 
//    None. 
// 
void PDU_ReleaseTrap( 
        RFC1157TrapPdu *pdu // Trap to release 
	) 
 
{ 
   SnmpUtilOidFree( &pdu->enterprise ); 
 
   // Free network address if dynamic 
   if ( pdu->agentAddr.dynamic ) 
      { 
      SnmpUtilMemFree( pdu->agentAddr.stream ); 
      } 
 
   SnmpUtilVarBindListFree( &pdu->varBinds ); 
} // PDU_ReleaseTrap 
 
 
 
// 
// PDU_ReleaseAnyPdu 
//    Determines what type of PDU it is and calls the appropriate routine 
//    to release it. 
// 
// Notes: 
// 
// Return Codes: 
//    SNMPAPI_NOERROR 
//    SNMPAPI_ERROR 
// 
// Error Codes: 
//    SNMP_PDUAPI_UNRECOGNIZED_PDU 
// 
SNMPAPI PDU_ReleaseAnyPDU( 
           IN OUT RFC1157Pdus *Pdu 
	   ) 
 
{ 
SNMPAPI nResult; 
 
 
   // Encode PDU/TRAP 
   switch ( Pdu->pduType ) 
      { 
      case ASN_RFC1157_GETREQUEST: 
      case ASN_RFC1157_GETNEXTREQUEST: 
      case ASN_RFC1157_GETRESPONSE: 
      case ASN_RFC1157_SETREQUEST: 
         PDU_ReleasePDU( &Pdu->pduValue.pdu ); 
         break; 
 
      case ASN_RFC1157_TRAP: 
         PDU_ReleaseTrap( &Pdu->pduValue.trap ); 
         break; 
 
      default: 
	 SetLastError( SNMP_PDUAPI_UNRECOGNIZED_PDU ); 
 
         nResult = SNMPAPI_ERROR; 
	 goto Exit; 
      } 
 
   nResult = SNMPAPI_NOERROR; 
 
Exit: 
   return nResult; 
} // PDU_ReleaseAnyPDU 
 
//-------------------------------- END --------------------------------------