?? snmp_decode.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 + -