Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

934 lines
22 KiB

/*++
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<xxxxx.h> ----
#include <stdlib.h>
//--------------------------- MODULE DEPENDENCIES -- #include"xxxxx.h" ------
#include <snmp.h>
#include <snmputil.h>
#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 --------------------------------------