?? a_decode.c
字號:
#include "snmptype.h"
#include "snmpdef.h"
#include "a_localio.h"
/****************************************************************************
NAME: A_DecodeTypeValue
PURPOSE: Decode the numeric part of an ASN.1 type from a stream.
The data stream is read using the local I/O package.
On exit, the stream poINT32er will be positioned to the byte
*AFTER* the type.
NOTE: The Class portion of the type is NOT decoded here, only the
value portion.
The user should call A_DecodeTypeClass *BEFORE* calling this
routine in order to get the class.
PARAMETERS: LCL_FILE * A stream descriptor (already open)
_INT16 * Receives an error code, if any.
RETURNS: _UINT16 The type value
RESTRICTIONS: It is assumed that the stream does not reach EOF before the
end of the field.
****************************************************************************/
_UINT16 A_DecodeTypeValue(LCL_FILE * lfile, _INT16 *errp)
{
_UINT8 oct;
oct = (_UINT8) (Lcl_Getc(lfile) & ~A_IDCF_MASK);
if(Lcl_Eof(lfile))
{
*errp = AE_PREMATURE_END;
return (_UINT16) 0;
}
if(oct != 0x1F)
{ /* Are there extension bytes? */
/* No extensions, type is in oct */
return (_UINT16) oct;
}
else
{ /* Type is in extension octets */
_UINT16 t = 0;
for(;;)
{
oct = (_UINT8) Lcl_Getc(lfile);
if(Lcl_Eof(lfile))
{
*errp = AE_PREMATURE_END;
return t;
}
if(!(oct & 0x80))
break; /* Hit final byte, we'll use */
/* it at the end of the loop */
t |= (_UINT16) (oct & 0x7F); /* Deal with a non-final byte */
t <<= 7;
}
t |= (_UINT16) oct; /* Take care of the final byte (the one */
/* without the 0x80 continuation bit.) */
return t;
}
/*NOTREACHED*/}
/****************************************************************************
NAME: A_DecodeLength
PURPOSE: Decode an ASN.1 length from a stream.
The data stream is read using the local I/O package.
On exit, the stream poINT32er will be positioned to the byte
*AFTER* the length.
PARAMETERS: LCL_FILE * Stream descriptor
_INT16 * Receives an error code, if any.
RETURNS: _UINT16 -- the length.
If the length is indefinite, (_UINT16)-1 is returned.
RESTRICTIONS: The stream must be open.
It is assumed that the stream will not reach EOF before the
length is decoded.
****************************************************************************/
_UINT16 A_DecodeLength(LCL_FILE * lfile, _INT16 *errp)
{
_UINT8 oct=0;
_UINT8 lsize=0;
_UINT16 len = 0;
oct = (_UINT8) Lcl_Getc(lfile);
if(Lcl_Eof(lfile))
{
*errp = AE_PREMATURE_END;
return (_UINT16) 0;
}
/* Indefinite form? */
if(oct == 0x80)
{
*errp = AE_INDEFINITE_LENGTH;
return (_UINT16) - 1;
}
if(!(oct & 0x80)) /* Short or long format? */
return (_UINT16) oct; /* Short format */
else
{ /* Long format */
lsize = oct & (_UINT8) 0x7F; /* Get # of bytes comprising length field */
while(lsize-- != 0)
{
len <<= 8;
len |= (_UINT8) Lcl_Getc(lfile);
if(Lcl_Eof(lfile))
{
*errp = AE_PREMATURE_END;
return (_UINT16) 0;
}
}
return len;
}
/*NOTREACHED*/
}
/********************
A_DecodeOctetStringData
PURPOSE: Pull an octet string from an ASN.1 stream.
The data stream is read using the local I/O package.
On entry stream poINT32er should be positioned to the first byte
of the data field.
On exit, the stream poINT32er will be positioned to at the start
of the next ASN.1 type field.
Parameters:
LCL_FILE * Stream descriptor
_UINT16 Length of octet string, from its ASN.1 header
_UINT8 * Control structure to receive the data.
_INT16 * Receives an error code, if any.
Returns: Nothing
Note: On return, the "start_bp" component of the buffer structure
poINT32s to a "malloc"-ed area in which the octet string is held.
Note that the octet string is NOT null terminated, may contain
INT32ernal nulls. A null poINT32er, (char *)0, is used if no area
is malloc-ed.
If the string is of zero length, a dummy buffer is established
which appears to be have a static buffer of length zero at
address zero.
********************/
void A_DecodeOctetStringData(LCL_FILE * stream, _UINT16 length,
_UINT8 * ebuffp,
_UINT16 maxEbuffLen,
_INT16 *errp)
{
_UINT16 got;
_UINT8 c;
*errp=0;
if((length != 0) && (length != (_UINT16) - 1))
{
if(length>maxEbuffLen) /*whr add*/
{
(void)Lcl_Read(stream, ebuffp,maxEbuffLen);
got=(length-maxEbuffLen);
while(got > 0)
{
c=Lcl_Getc(stream);
if(Lcl_Eof(stream))
break;
--got;
}
}
else
got=Lcl_Read(stream, ebuffp, length);
}
}
/********************
A_DecodeOctetStringWTC
PURPOSE: Pull an octet string from an ASN.1 stream.
The data stream is read using the local I/O package.
On entry stream poINT32er should be positioned to the first byte
of the octet string's type field.
This version does type checking.
On exit, the stream poINT32er will be positioned to at the start
of the next ASN.1 type field.
Parameters:
LCL_FILE * Stream descriptor
_UINT8 * Control structure to receive the data.
_INT16 * Receives an error code, if any.
_UINT16 The type value
_UINT8 A_IDC_MASK flag values
Returns: Nothing
Note: On return, the "start_bp" component of the buffer structure
poINT32s to a "malloc"-ed area in which the octet string is held.
Note that the octet string is NOT null terminated, may contain
INT32ernal nulls. A null poINT32er, (char *)0, is used if no area
is malloc-ed.
********************/
void A_DecodeOctetStringWTC(LCL_FILE * stream,
_UINT8 * ebuffp, _UINT16 maxLen,
_INT16 *errp, _UINT16 id, _UINT8 flags)
{
_UINT16 os_length;
if((A_DecodeTypeClass(stream) != flags) || (A_DecodeTypeValue(stream, errp) != id))
{
if(*errp == 0)
*errp = AE_WRONG_TYPE;
/* On a decoding error, pretend we have a zero length string */
return;
}
os_length = A_DecodeLength(stream, errp);
if(os_length>maxLen)
{
if(*errp == 0)
*errp = AUTHORIZATION_ERROR;
return;
}
if(*errp == 0)
{
A_DecodeOctetStringData(stream,os_length,ebuffp,maxLen,errp);
}
}
/********************
A_DecodeIntegerData
PURPOSE: Pull an INT32eger from an ASN.1 stream.
The data stream is read using the local I/O package.
On entry stream poINT32er should be positioned to the first byte
of the data field.
On exit, the stream poINT32er will be positioned to at the start
of the next ASN.1 type field.
Parameters:
LCL_FILE * Stream descriptor
_UINT16 Length of contents field, from the ASN.1 header
_INT16 * Receives an error code, if any.
Returns: _INT16 (See note below)
NOTE: If the received value is really unsigned, then the caller should
merely cast the value returned by this procedure to an _UINT32.
WARNING: If the INT32eger occupies more than 4 octets, then high order precision
will be lost, including the sign bit. For unsigned values in which the
basic value occupies all 4 octets, the sign octet, containing a zero sign
bit, will be lost but will not damage the returned value.
********************/
_INT32 A_DecodeIntegerData(LCL_FILE * stream, _UINT16 length, _INT16 *errp)
{
_INT32 ivalue = 0;
_INT32 firstone = 1;
_UINT8 oct;
while(length-- != 0)
{
oct = (_UINT8) Lcl_Getc(stream);
if(Lcl_Eof(stream))
{
*errp = AE_PREMATURE_END;
return ivalue;
}
/* See whether we are receiving something that has the sign bit set, or
* if this is a 5 byte unsigned _INT32 check the first byte, it must be 0 */
if(firstone)
{
firstone = 0;
if((length == 4) && (oct != 0))
{
*errp = AE_WRONG_VALUE;
return ivalue;
}
if(oct & (_UINT8) 0x80)
ivalue = (_INT32) - 1;
}
/*lINT32 -e703 */
ivalue <<= 8;
/*lINT32 +e703 */
ivalue |= oct; /* 'oct' better not be sign extended!!! */
}
return ivalue;
}
/********************
A_DecodeIntegerWTC
PURPOSE: Pull an INT32eger from an ASN.1 stream.
The data stream is read using the local I/O package.
On entry stream poINT32er should be positioned to the first byte
of the INT32eger's ASN.1 type field.
As we pull off the class and type we check them against
the arguments to make sure they are correct.
On exit, the stream poINT32er will be positioned to at the start
of the next ASN.1 type field.
Parameters:
LCL_FILE * Stream descriptor
_INT16 * Receives an error code, if any.
_UINT16 The type value
_UINT8 A_IDC_MASK flag values
Returns: _INT32;
********************/
_INT32 A_DecodeIntegerWTC(LCL_FILE * stream, _INT16 *errp, _UINT16 id, _UINT8 flags)
{
_UINT16 INT32_length;
if((A_DecodeTypeClass(stream) != flags) || (A_DecodeTypeValue(stream, errp) != id))
{
if(*errp == 0)
*errp = AE_WRONG_TYPE;
return (0);
}
INT32_length = A_DecodeLength(stream, errp);
if(*errp == 0)
{
if(INT32_length > 5)
*errp = AE_WRONG_VALUE;
else
return A_DecodeIntegerData(stream, INT32_length, errp);
}
return (0);
}
/********************
A_DecodeObjectIdData
PURPOSE: Pull an object identifier from an ASN.1 stream.
The data stream is read using the local I/O package.
On entry stream poINT32er should be positioned to the first byte
of the data field.
On exit, the stream poINT32er will be positioned to at the start
of the next ASN.1 type field.
Parameters:
LCL_FILE * Stream descriptor
_UINT16 Length of contents field, from the ASN.1 header
OBJ_ID_T * Object identifier structure to receive the object id.
The "component_list" will be "malloc"ed.
component_list == (_UINT32 *)0 indicates that
there is no component_list.
_INT16 * Receives an error code, if any.
Returns: Nothing
********************/
void A_DecodeObjectIdData(LCL_FILE * stream, _UINT16 length, OBJ_ID_T * objp, _INT16 *errp)
{
_UINT16 content_offset; /* Offset in stream where contents begins */
_INT16 subids=0;
_INT32 left; /* Count of unused contents bytes */
_UINT16 j=0; /* Number of subidentifiers */
_INT16 subid_num;
_UINT32 subid_val; /* Value of a subidentifier */
_UINT32 cp[MAX_OID_LENGTH];
_UINT8 c, first_c;
_INT16 subid_bytes; /* number of bytes in this sub id */
_INT16 subid_done; /* flag to see if the sub id is finished */
objp->num_components = 0;
(void)memset((_UINT8 *)(&cp[0]),0,sizeof(cp));
/* Remember where the contents begins */
content_offset = Lcl_Tell(stream);
/* Count the number of components */
for(subids = 0, left = (_INT32) length; left > 0;)
{
first_c = (_UINT8) Lcl_Getc(stream);
if(Lcl_Eof(stream))
{
*errp = AE_PREMATURE_END;
return;
}
left--;
/* if its not the last (only) byte, step through the rest of the bytes */
if(first_c & 0x80)
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -