⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 a_decode.c

📁 在freescale 的ne64上开发的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
#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 + -