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

📄 snmp_decode.c

📁 在freescale 的ne64上开发的源代码
💻 C
字号:
#include "snmptype.h"
#include "snmpdef.h"
#include "snmpfunc.h"
#ifdef SNMP_STATISTIC
#define SNMPv1v2_INC_COUNTER
#endif
t_Community gCommunity[MAX_TRAP_SERVER_NUM]={{"public",RO},{"NETMAN",RW},{"",RO},{"",RO},{"",RO}};;
_INT16 SNMP_Community_Validate(SNMP_PKT_T * rp)
{
	/*tinyang*/
	_UINT8 i;
	for(i=0;i<5;i++)
	{	
#if 0
		if(gCommunity[i].ability==0)
		{
			printf(" snmp community %d %s ro\n\r",i+1,gCommunity[i].name);
			printf(" snmp community %d %s ro\n\r",i+1,rp->community);	
		}
		else
		{
			printf(" snmp community %d %s rw\n\r",i+1,gCommunity[i].name);
			printf(" snmp community %d %s rw\n\r",i+1,rp->community);
		}
#endif
		if(strcmp(rp->community,gCommunity[i].name)==0)
		{	
			if((rp->pdu_type==SET_REQUEST_PDU) && (gCommunity[i].ability==RO))
			{
				
				return (2);
			}
			else
				return (0);
		}

	}
	return (2);
}

_INT16 Count_Var_Binds(LCL_FILE * stream, _UINT16 length)
{
	/* tell_place is the offset in stream to VarBind data */
	_UINT16 used, tell_place;
	_INT16 items;
	_INT16 asn1err = 0;
	_UINT16 alength=0, start_place=0, end_place=0;
	tell_place = Lcl_Tell(stream);
	for(items = 0, used = 0; used < length;)
	{
		start_place = Lcl_Tell(stream);
		if(Lcl_Eof(stream))
			break;

		/* Skip over the VarBind sequence */
		(void) A_DecodeTypeValue(stream, &asn1err);
		alength = A_DecodeLength(stream, &asn1err);
		if(asn1err || (Lcl_Seek(stream, alength, 1) < 0))
		{
			items = (DECODE_ASN_PARSE_ERROR);
			break;
		}

		end_place = Lcl_Tell(stream);
		used = used + end_place - start_place;
		items++;
		if(items>MAX_SUPPORT_OID_NUM)
			return (MAX_SUPPORT_OID_NUM+1);
	}
	(void) Lcl_Seek(stream, tell_place, 0);
	return items;
}
/****************************************************************************
NAME:  Decode_Pkt_To_Vb

PURPOSE:  Decode a VarBind from a packet
          On entry the input stream should be positioned to the tag field
          of the VarBind entry.
          On exit, the stream poINT32er will be positioned to at the start
          of the ASN.1 type field of AFTER the VarBind.

PARAMETERS:
        SNMP_PKT_T *    The packet being decoded.
        _UINT8   *    The input packet.

RETURNS:  success:  TRUE
          	  else FALSE
****************************************************************************/
_INT16 Decode_Pkt_To_Vb(LCL_FILE * stream, VB_T * vbp, SNMP_PKT_T * rp)
{
	_UINT8 flags;
	_UINT16 id;
	_UINT16 leng;
	_INT16 asn1err = 0;
	(void)A_DecodeObjectIdWTC(stream, &(vbp->vb_obj_id), &asn1err, A_OBJECTID, A_UNIVERSAL | A_PRIMITIVE);
	flags = A_DecodeTypeClass(stream);
	id = A_DecodeTypeValue(stream, &asn1err);
	leng = A_DecodeLength(stream, &asn1err);
	if(asn1err)
	{
		return (DECODE_ASN_PARSE_ERROR);
	}
	vbp->vb_data_length = leng;
	vbp->vb_data_flags_n_type = flags | (_UINT8) id;
	switch (vbp->vb_data_flags_n_type)
	{
	case VT_NUMBER:
		vbp->value_u.v_number = A_DecodeIntegerData(stream, leng, &asn1err);
		break;
	case VT_COUNTER:
	case VT_GAUGE:
	case VT_TIMETICKS:
		vbp->value_u.v_counter = (_UINT32) A_DecodeIntegerData(stream, leng, &asn1err);
		break;
	case VT_STRING:
	case VT_OPAQUE:
		(void)A_DecodeOctetStringData(stream, leng, vbp->value_u.v_string,MAX_OCTET_LENGTH,&asn1err);
		break;
	case VT_OBJECT:
		(void)A_DecodeObjectIdData(stream, leng, &(vbp->value_u.v_object), &asn1err);
		break;
	case VT_NOSUCHOBJ:
	case VT_NOSUCHINS:
	case VT_ENDOFMIB:
	case VT_EMPTY:
		/* Empty has no contents to be decoded */
		break;
	case VT_IPADDRESS:
		(void)A_DecodeOctetStringData(stream, leng,vbp->value_u.v_network_address,4,&asn1err);
		break;		
	case VT_COUNTER64:
		if(rp->snmp_version == SNMP_VERSION_1)
		{
			return (DECODE_ASN_PARSE_ERROR);
		}
		(void)A_DecodeInteger64Data(stream, leng, &(vbp->value_u.v_counter64), &asn1err);
		break;
	default:
		return (DECODE_ASN_PARSE_ERROR);
	}
	if(asn1err)
		return (DECODE_ASN_PARSE_ERROR);
	else
		return 0;
	/*NOTREACHED*/
}

_INT16 Decode_Pkt_To_VbList(LCL_FILE * stream, SNMP_PKT_T * rp)
{
	VB_T *vbp;
	_INT16 i=0;
	_INT16 asn1err = 0;
	/* Now deal with the VarBindList and sanity check the length field */
	(void)A_DecodeTypeValue(stream, &asn1err);
	rp->pdu.vbl_length = A_DecodeLength(stream, &asn1err);
	if(asn1err || (rp->pdu.vbl_length != Lcl_Size(stream)))
	{
		return (DECODE_ASN_PARSE_ERROR);
	}
	/* Count the number of VarBinds.*/
	rp->pdu.vb_count = Count_Var_Binds(stream, rp->pdu.vbl_length);	
	if(rp->pdu.vb_count>MAX_SUPPORT_OID_NUM)
	{
		return (DECODE_ASN_PARSE_ERROR);
	}
	if(rp->pdu.vb_count >= 0xffff )
	{
		return (DECODE_ASN_PARSE_ERROR);
	}
	/* The VarBindList has contents */
	for(i=0;i<rp->pdu.vb_count;i++)
	{
		vbp=(VB_T *)(&(rp->pdu.vb_obj[i]));
		(void)A_DecodeTypeValue(stream, &asn1err);
		vbp->vb_seq_size = A_DecodeLength(stream, &asn1err);
		if(asn1err || Decode_Pkt_To_Vb(stream, vbp, rp))
		{
			return (DECODE_ASN_PARSE_ERROR);
		}
	}
	return 0;
}

_INT16 SNMP_Decode_PDU(SNMP_PKT_T * rp, LCL_FILE * in_stream)
{
	_INT16 asn1err = 0;
#ifdef SNMP_SUPPORT_TRAP
	if(rp->pdu_type == TRAP_PDU)
	{
		EBUFFER_T net_addr;
		_UINT32 used;
		rp->pdu.trap_pdu.trap_vbl.vblist = 0;
		(void)EBufferInitialize(&net_addr);
		(void)A_DecodeObjectIdWTC(in_stream, &(rp->pdu.trap_pdu.enterprise_objid),&asn1err, A_OBJECTID, A_UNIVERSAL | A_PRIMITIVE);
		(void)A_DecodeOctetStringWTC(in_stream, &net_addr, &asn1err,VT_IPADDRESS & ~A_IDCF_MASK, VT_IPADDRESS & A_IDCF_MASK);
		rp->pdu.trap_pdu.generic_trap = A_DecodeIntegerWTC(in_stream,&asn1err, A_INTEGER,A_UNIVERSAL | A_PRIMITIVE);
		rp->pdu.trap_pdu.specific_trap = A_DecodeIntegerWTC(in_stream, &asn1err, A_INTEGER, A_UNIVERSAL | A_PRIMITIVE);
		rp->pdu.trap_pdu.trap_time_ticks = (_UINT32) A_DecodeIntegerWTC(in_stream, &asn1err, VT_TIMETICKS & ~A_IDCF_MASK, VT_TIMETICKS & A_IDCF_MASK);
		if(asn1err)
		{
			(void)EBufferClean(&net_addr);
			return (DECODE_ASN_PARSE_ERROR);
		}
		(void)memset(rp->pdu.trap_pdu.net_address, 0, 4);
		used = min(4, EBufferUsed(&net_addr));
		if(used != 0)
		{
			(void)memcpy(rp->pdu.trap_pdu.net_address, net_addr.start_bp, used);
			(void)EBufferClean(&net_addr);
		}
		/* Now deal with the VarBindList */
		return (Decode_Pkt_To_VbList(in_stream,rp));
	}/* if (ptype == TRAP_PDU) */
#endif
	/* if we get here it's a non-trap form of pdu */
	rp->pdu.request_id = (_INT32)A_DecodeIntegerWTC(in_stream, &asn1err,A_INTEGER, A_UNIVERSAL | A_PRIMITIVE);
	rp->pdu.error_status = (_UINT16)A_DecodeIntegerWTC(in_stream, &asn1err,A_INTEGER, A_UNIVERSAL | A_PRIMITIVE);
	rp->pdu.error_index = (_UINT16)A_DecodeIntegerWTC(in_stream, &asn1err,A_INTEGER, A_UNIVERSAL | A_PRIMITIVE);
#if 0
	if(rp->pdu_type==GET_BULK_REQUEST_PDU)
	{
		rp->pdu.error_status=0;
		rp->pdu.error_index=0;
	}
#else
	rp->pdu.error_status=0;
	rp->pdu.error_index=0;
#endif
	if(asn1err)
	{
		return (DECODE_ASN_PARSE_ERROR);
	}
	/* Now deal with the VarBindList */
	return (Decode_Pkt_To_VbList(in_stream,rp));
}

/****************************************************************************
NAME:  SNMP_Decode_V1_Packet

PURPOSE:  Decode an V1 (RFC1157) or V2 SNMP packet.

PARAMETERS:
        SNMP_PKT_T *    Packet we're filling in.
        _UINT8 *    original received packet.
        _UINT32	  packet length
        _UINT8 *    error return, if it is (_INT32 *)0, don't
                        return an error.

RETURNS:  void
****************************************************************************/

_INT16 SNMP_Decode_V1V2_Packet(SNMP_PKT_T * rp,LCL_FILE * in_stream,_UINT16 asn1leng)
{
	_UINT16 ptype;
	_UINT16 plength;
	_INT16 asn1err = NO_ERROR;
	_UINT16 error_status=0;
	/* Extract the community string */
	(void)A_DecodeOctetStringWTC(in_stream, rp->community,MAX_COMMUNITY_LEN,
			&asn1err,A_OCTETSTRING, A_UNIVERSAL | A_PRIMITIVE);
	if(asn1err)
	{
#ifdef SNMP_STATISTIC
		SNMPv1v2_INC_COUNTER(snmp_stats.snmpInASNParseErrs);
#endif
		rp->pdu.error_status=GEN_ERR;/*whr add*/		
		return (-1);
	}

	/* Decode the packet type                                             */
	/* Since all of the PDUs follow the same form, we can decode them     */
	/* without being concerned as to which PDU we are decoding.           */
	/* Furthermore, since the VarBindList is the last thing in the PDU,   */
	/* we can ignore the overall length of the sequence forming the PDU.  */

	if(A_DecodeTypeClass(in_stream) != (A_DEFAULT_SCOPE | A_CONSTRUCTOR))
	{
#ifdef SNMP_STATISTIC
		SNMPv1v2_INC_COUNTER(snmp_stats.snmpInASNParseErrs);
#endif
		rp->pdu.error_status=GEN_ERR;
		return (-1);
	}

	/* Decode the pdu type */
	ptype = A_DecodeTypeValue(in_stream, &asn1err);
	plength = A_DecodeLength(in_stream, &asn1err);

	if(asn1err)
	{
#ifdef SNMP_STATISTIC
		SNMPv1v2_INC_COUNTER(snmp_stats.snmpInASNParseErrs);
#endif
		rp->pdu.error_status=GEN_ERR;
		return (-1);
	}

	/* Determine if we support the given pdu for the given version */
	switch (rp->snmp_version)
	{
		case SNMP_VERSION_1:
		case SNMP_VERSION_2:
			break;
		default:
#ifdef SNMP_STATISTIC
		SNMPv1v2_INC_COUNTER(snmp_stats.snmpInBadVersions);
#endif
		rp->pdu.error_status=GEN_ERR;
		return (-1);
	}
	/* Check whether there is an inconsistency between the PDU length and */
	/* the overall length indicated by the outermost ASN.1 wrapper.       */
	/* If so, the packet is ill-formed and must be rejected.              */
	if(asn1leng != (Lcl_Tell(in_stream) + plength))
	{
#ifdef SNMP_STATISTIC
		SNMPv1v2_INC_COUNTER(snmp_stats.snmpInASNParseErrs);
#endif
		rp->pdu.error_status=GEN_ERR;
		return (-1);
	}

	rp->pdu_type = (_UINT8)ptype;
	if(ptype==GET_BULK_REQUEST_PDU)
		rp->pdu_type=GET_NEXT_REQUEST_PDU;
	rp->pdu_length = plength;

	/* Check that the community string is valid.  This also gets the      */
	/* view mask for this transaction from the community string.  The     */
	/* source and destination addresses are passed through for the user   */
	/* routine to deal with.  It may just copy them INT32o the snmp packet  */
	/* structure.                                                         */
#if 1
	switch (SNMP_Community_Validate(rp))
	{
		case 0:
			break;
		case 2:
#ifdef SNMP_STATISTIC
			SNMPv1v2_INC_COUNTER(snmp_stats.snmpInBadCommunityNames);
#endif
			error_status=AUTHORIZATION_ERROR;
			break;
		case 3:
#ifdef SNMP_STATISTIC
			SNMPv1v2_INC_COUNTER(snmp_stats.snmpInBadCommunityUses);
#endif
			error_status=AUTHORIZATION_ERROR;
			break;
		case 1:
		default:
			error_status=AUTHORIZATION_ERROR;
			break;
	}
#endif
	switch (SNMP_Decode_PDU(rp, in_stream))
	{
		case 0:
			{
			rp->pdu.error_status=error_status;
			if(rp->pdu.error_status!=NO_ERROR)
				return (-1);
			else
				return NO_ERROR;
			}
		case DECODE_ASN_PARSE_ERROR:
#ifdef SNMP_STATISTIC
			SNMPv1v2_INC_COUNTER(snmp_stats.snmpInASNParseErrs);
#endif
			rp->pdu.error_status=GEN_ERR;
			return (-1);
		case DECODE_ALLOCATION_FAILURE:
		default:
			rp->pdu.error_status=GEN_ERR;
			return (-1);
	}
	return NO_ERROR;
}


_INT16 SNMP_Decode_Packet_WER(_UINT8 *ebuffp,_UINT16 pktl,SNMP_PKT_T *rp)
{
	_UINT16 type;
	_UINT16 overall_length, asn1leng;
	_UINT8 flags;
	LCL_FILE *in_stream, in_pkt_stream;
	_INT16 asn1err = 0;
	_INT16 snmp_version;
	/* if the caller did not supply error_ret set that up and
	 * init it to the no error state */
	rp->pdu.error_status = NO_ERROR;
	/* Make sure the size is within range and then Set up packet as a local stream. */
	if((in_stream = Lcl_Open(&in_pkt_stream, ebuffp, (_UINT16) pktl)) == 0)
	{
		rp->pdu.error_status = GEN_ERR;	/*whr add */
		return (-1);
	}
	/* Decode the top-level message sequence... */
	flags = A_DecodeTypeClass(in_stream);
	type = A_DecodeTypeValue(in_stream, &asn1err);
	overall_length = A_DecodeLength(in_stream, &asn1err);
	if(asn1err)
	{
#ifdef SNMP_STATISTIC
		SNMPv1v2_INC_COUNTER(snmp_stats.snmpInASNParseErrs);
#endif
		rp->pdu.error_status=GEN_ERR;/*whr add */
		return (-1);
	}
	/* Validate that the length provided by the caller is consistent with */
	/* the length given by the ASN.1 wrapper...                           */
	/* If necessary, shrink the local I/O buffer to match.                */
	asn1leng = Lcl_Tell(in_stream) + overall_length;
	if(asn1leng < (_UINT16) pktl)
	{		
		in_stream->lbuf_end = (_UINT8 *) (in_stream->lbuf_start + asn1leng);
		if(in_stream->lbuf_next < in_stream->lbuf_end)
			in_stream->lcl_flags &= ~LCL_EOF;
		else
			in_stream->lcl_flags |= LCL_EOF;
	}
	else
	{
		if(asn1leng > (_UINT16) pktl)
		{
#ifdef SNMP_STATISTIC
			SNMPv1v2_INC_COUNTER(snmp_stats.snmpInASNParseErrs);
#endif
			rp->pdu.error_status=GEN_ERR;/*whr add */
			return (-1);
		}
	}
	/* Test the flags & type info to see if we have something that
	 * looks like the right kind of packet */
	if((flags | type) != (A_UNIVERSAL | A_CONSTRUCTOR | A_SEQUENCE))
	{
		/* oh well, this isn't an snmp packet, bail out */
#ifdef SNMP_STATISTIC
		SNMPv1v2_INC_COUNTER(snmp_stats.snmpInASNParseErrs);
#endif
		rp->pdu.error_status=GEN_ERR;/*whr add */
		return (-1);
	}
	/* get the version stamp */
	snmp_version = (_INT16)A_DecodeIntegerWTC(in_stream, &asn1err, A_INTEGER, A_UNIVERSAL | A_PRIMITIVE);
	if(asn1err)
	{
#ifdef SNMP_STATISTIC
		SNMPv1v2_INC_COUNTER(snmp_stats.snmpInASNParseErrs);
#endif
		rp->pdu.error_status=GEN_ERR;/*whr add */
		return (-1);
	}
	rp->snmp_version = snmp_version;
	switch (snmp_version)
	{
	case SNMP_VERSION_1:
	case SNMP_VERSION_2:
		asn1err = SNMP_Decode_V1V2_Packet(rp,in_stream,asn1leng);/*whr add error_ret*/
		break;
	default:
#ifdef SNMP_STATISTIC
		if((snmp_version < SNMP_VERSION_MIN) || (snmp_version > SNMP_VERSION_MAX))
			SNMPv1v2_INC_COUNTER(snmp_stats.snmpInASNParseErrs);
		else
			SNMPv1v2_INC_COUNTER(snmp_stats.snmpInBadVersions);
#endif
		asn1err = -1;
		rp->pdu.error_status=GEN_ERR;/*whr add */
		break;
	}
	if(asn1err)
	{
		return (-1);
	}
	else
		return (NO_ERROR);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -