📄 v3_ber.c
字号:
PARAMETERS: SNMP_PKT_T * Packet we're filling in. LCL_FILE * Stream to decode packet from. The stream is positioned at the start of the scoped pdu SNMPADDR_T * Source of the packet SNMPADDR_T * Destination of the packet (most likely the address of the machine on which this code is running.) int * length of packet SNMP_USER_T * RETURNS: int 2 = response packet ready to go (we're sending back an error) 1 = success 0 = no processing reqired (validation, resource problems etc). errors************************************************************************/int decode_scoped_pdu(SNMP_PKT_T * rp, LCL_FILE * in_stream, SNMPADDR_T * pktsrc, SNMPADDR_T * pktdst, ALENGTH_T asn1leng, SNMP_USER_T * user){ALENGTH_T asn_length;ATVALUE_T asn_value;int asn_err = 0;SNMP_GROUP_T *group;SNMP_ACCESS_T *access = 0;sbits32_t sec_level;/* Pull out the context information */if ((A_DecodeTypeClass(in_stream) != (A_UNIVERSAL | A_CONSTRUCTOR)) || (A_DecodeTypeValue(in_stream, &asn_err) != A_SEQUENCE)) return (DECODE_ASN_PARSE_ERROR);asn_length = A_DecodeLength(in_stream, &asn_err);if (asn_length > Lcl_Size(in_stream)) return (DECODE_ASN_PARSE_ERROR);(void) Lcl_Resize(in_stream, asn_length, 1);A_DecodeOctetStringWTC(in_stream, &rp->msg_con_id, &asn_err, A_OCTETSTRING, A_UNIVERSAL | A_PRIMITIVE);A_DecodeOctetStringWTC(in_stream, &rp->community, &asn_err, A_OCTETSTRING, A_UNIVERSAL | A_PRIMITIVE);if (asn_err) return(DECODE_ASN_PARSE_ERROR);/* Decode the pdu type and length and sanity check them */if (A_DecodeTypeClass(in_stream) != (A_DEFAULT_SCOPE | A_CONSTRUCTOR)) return(DECODE_ASN_PARSE_ERROR);asn_value = A_DecodeTypeValue(in_stream, &asn_err);asn_length = A_DecodeLength(in_stream, &asn_err);if (asn_err || (asn_value > MAX_PDU) || (asn_value == TRAP_PDU) || (asn_length > Lcl_Size(in_stream))) return(DECODE_ASN_PARSE_ERROR);rp->pdu_type = asn_value;rp->pdu_length = asn_length;if (SNMP_validate_address(rp, pktsrc, pktdst)) return(0);switch(SNMP_Decode_PDU(rp, in_stream)) { case 0:#if INSTALL_ENVOY_SNMP_V3_PROXY /* Check to see if I have the data, that is, does the context engine id equal mine? If not, and we're using SNMPv3 proxies, we may need to forward this packet. */ if ((EBufferUsed(&rp->msg_con_id) < ETC_ENGINE_ENGINE_MIN) || (EBufferUsed(&rp->msg_con_id) > ETC_ENGINE_ENGINE_MAX)) return(DECODE_UNKNOWN_PDU_HANDLERS); if ((SNMP_Engine_Get_My_ID_Length() != EBufferUsed(&rp->msg_con_id)) || (MEMCMP(EBufferStart(&rp->msg_con_id), SNMP_Engine_Get_My_ID(), SNMP_Engine_Get_My_ID_Length()))) { switch(rp->pdu_type) { case GET_REQUEST_PDU: case GET_NEXT_REQUEST_PDU: case SET_REQUEST_PDU: case GET_BULK_REQUEST_PDU: rp->proxy_routine = (PROXY_ROUTINE_T *) snmpProxyV3Request; break; case INFORM_REQUEST_PDU: case TRAP2_PDU: rp->proxy_routine = (PROXY_ROUTINE_T *) snmpProxyV3Notify; break; case GET_RESPONSE_PDU: case REPORT_PDU: rp->proxy_routine = (PROXY_ROUTINE_T *) snmpProxyV3Response; break; default: rp->proxy_routine = 0; return(0); } return(1); } /* If we need to try to get a view for the packet */ if ((rp->pdu_type != GET_REQUEST_PDU) && (rp->pdu_type != GET_NEXT_REQUEST_PDU) && (rp->pdu_type != SET_REQUEST_PDU) && (rp->pdu_type != GET_BULK_REQUEST_PDU)) /* no need */ return(1);#else /* #if INSTALL_ENVOY_SNMP_V3_PROXY */ /* If we need to try to get a view for the packet */ if ((rp->pdu_type != GET_REQUEST_PDU) && (rp->pdu_type != GET_NEXT_REQUEST_PDU) && (rp->pdu_type != SET_REQUEST_PDU) && (rp->pdu_type != GET_BULK_REQUEST_PDU)) /* no need */ return(1); /* Check to see if I have the data, that is, does the context engine id equal mine? If not, we should just discard the PDU. */ if ((SNMP_Engine_Get_My_ID_Length() != EBufferUsed(&rp->msg_con_id)) || (MEMCMP(EBufferStart(&rp->msg_con_id), SNMP_Engine_Get_My_ID(), SNMP_Engine_Get_My_ID_Length()))) return(DECODE_UNKNOWN_PDU_HANDLERS);#endif /* #if INSTALL_ENVOY_SNMP_V3_PROXY */ /* Check to see if this message is for me, that is, does the auth engine id equal mine? Currently there isn't a report for this condition */ if ((SNMP_Engine_Get_My_ID_Length() != EBufferUsed(&rp->msg_sec_id)) || (MEMCMP(EBufferStart(&rp->msg_sec_id), SNMP_Engine_Get_My_ID(), SNMP_Engine_Get_My_ID_Length()))) return(0); if (SNMP_V3_Context_Find(EBufferStart(&rp->community), EBufferUsed(&rp->community)) == 0) { return(DECODE_UNKNOWN_CONTEXTS); } group = SNMP_Group_Lookup(rp->msg_sec_model, SNMP_User_Get_SName(user), SNMP_User_Get_SName_Len(user)); if (group && (SNMP_Group_Get_Status(group) == ETC_RS_ACTIVE)) { if (rp->msg_flags & ETC_V3_PRIV) sec_level = ETC_SEC_LEVEL_PRIV; else if (rp->msg_flags & ETC_V3_AUTH) sec_level = ETC_SEC_LEVEL_AUTH; else sec_level = ETC_SEC_LEVEL_NONE; access = SNMP_V3_Access_Find(SNMP_Group_Get_Group(group), SNMP_Group_Get_Group_Len(group), EBufferStart(&rp->community), EBufferUsed(&rp->community), rp->msg_sec_model, sec_level); } /* turn off the report flags as we won't be generating more reports, if we need a report later in the code this line will need to be moved accordingly. */ rp->msg_flags &= (ETC_V3_AUTH | ETC_V3_PRIV); if (access) { bits8_t *vname; ALENGTH_T vlen; if (rp->pdu_type == SET_REQUEST_PDU) { vname = SNMP_V3_Access_Get_Write(access); vlen = SNMP_V3_Access_Get_Write_Len(access); } else { vname = SNMP_V3_Access_Get_Read(access); vlen = SNMP_V3_Access_Get_Read_Len(access); } if ((vname == 0) || (vlen == 0)) { rp->pdu.std_pdu.error_status = AUTHORIZATION_ERROR; rp->pdu.std_pdu.error_index = 0; return(2); } if (EBufferAllocateLoad(BFL_IS_ALLOC, &rp->view_name, vname, vlen)) return(0); } else { rp->pdu.std_pdu.error_status = AUTHORIZATION_ERROR; rp->pdu.std_pdu.error_index = 0; return(2); } return(1); case DECODE_ASN_PARSE_ERROR: return(DECODE_ASN_PARSE_ERROR); case DECODE_ALLOCATION_FAILURE: default: return(0); }}#if INSTALL_ENVOY_SNMP_V3_TARGET#if defined(ENVOY_USE_DEFAULT_TADDRESS) && (INSTALL_ATTACHE)/****************************************************************************NAME: envoy_taddress_to_snmpaddrPURPOSE: Convert the data in a TAddress TC format into an SNMPADDR_T. This function will only handle those TAddress in the TDomain of snmpUDPDomain. Note that this function may be overridden by a customer user-exit.PARAMETERS: SNMPADDR_T * The SNMPADDR to convert into OBJ_ID_T * The TDomain of the TAddress EBUFFER_T * The TAddressRETURNS: 0 if translation successful, -1 otherwise****************************************************************************/int envoy_taddress_to_snmpaddr(SNMPADDR_T *addr, OBJ_ID_T *tdomain, EBUFFER_T *taddress){bits16_t port;if (!oidcmp(sizeof_snmpUDPDomain, snmpUDPDomain, tdomain->num_components, tdomain->component_list)) return -1;MEMSET(addr, 0, sizeof(SNMPADDR_T));MEMCPY(addr->snmp_data, EBufferStart(taddress), sizeof(bits32_t));MEMCPY(&port, EBufferStart(taddress) + sizeof(bits32_t), sizeof(bits16_t));addr->snmp_port = SWAP16(port);return 0;}#endif /* ENVOY_USE_DEFAULT_TADDRESS */#if defined(ENVOY_USE_DEFAULT_SNMPADDR) && (INSTALL_ATTACHE)/****************************************************************************NAME: envoy_snmpaddr_to_taddressPURPOSE: Convert an SNMPADDR_T to a TAddress and TDomain. This function only deals with SNMPADDR_Ts formatted in the Attache style.PARAMETERS: SNMPADDR_T * The SNMPADDR to convert from OBJ_ID_T * The TDomain of the TAddress EBUFFER_T * The TAddressRETURNS: 0 if translation successful, -1 otherwise****************************************************************************/int envoy_snmpaddr_to_taddress(SNMPADDR_T *addr, OBJ_ID_T *tdomain, EBUFFER_T *taddress){bits8_t taddr[6];bits16_t port;if (build_object_id(sizeof_snmpUDPDomain, snmpUDPDomain, tdomain)) return -1;MEMCPY(taddr, addr->snmp_data, 4);port = SWAP16(addr->snmp_port);MEMCPY((taddr+4), &port, sizeof(bits16_t));EBufferAllocateLoad(BFL_IS_ALLOC, taddress, taddr, 6);return 0;}#endif /* ENVOY_USE_DEFAULT_SNMPADDR *//************************************************************************NAME: envoy_add_engine_addressPURPOSE: Add an engine id and address to the engine list.PARAMETERS: SNMP_PKT_T * Packet we're getting our information from. SNMPADDR_T * Generalized form of address packet came from. int if 0, we need to add the engine id. Otherwise, we just add the address to it.RETURNS: 1 if an engine was successfully added, 0 otherwise************************************************************************/int envoy_add_engine_address(SNMP_PKT_T *rp, SNMPADDR_T *address, int create){int success = 0;OBJ_ID_T tdomain;EBUFFER_T taddress;if (create == 0) { success = SNMP_Engine_Install(EBufferStart(&(rp->msg_sec_id)), EBufferUsed(&(rp->msg_sec_id)), rp->msg_sec_boots, rp->msg_sec_time); if (success == -1) return(0); }EBufferInitialize(&taddress);init_object_id(&tdomain);if (ENVOY_SNMPADDR_TO_TADDRESS(address, &tdomain, &taddress) == 0) { SNMP_Engine_Set_Address(EBufferStart(&(rp->msg_sec_id)), EBufferUsed(&(rp->msg_sec_id)), tdomain.component_list, tdomain.num_components, EBufferStart(&taddress), EBufferUsed(&taddress)); }Clean_Obj_ID(&tdomain);EBufferClean(&taddress);return(1);}#endif/************************************************************************NAME: SNMP_Decode_V3_PacketPURPOSE: Decode a V3 packet, the localio will point to the first byte after the version stamp. If the error_ret flag is set then the returned packet is a report packet and should be sent to the requester.PARAMETERS: SNMP_PKT_T * Packet we're filling in. LCL_FILE * Stream to decode packet from. The stream is positioned after the first tag field (the tag that says it's a V3 packet) SNMPADDR_T * Source of the packet SNMPADDR_T * Destination of the packet (most likely the address of the machine on which this code is running.) ALENGTH_T asn1 length int * error returnRETURNS: SNMP_PKT_T * SNMP Packet structure, 0 on failure************************************************************************/SNMP_PKT_T * SNMP_Decode_V3_Packet(SNMP_PKT_T * rp, LCL_FILE * in_stream, SNMPADDR_T * pktsrc, SNMPADDR_T * pktdst, ALENGTH_T asn1leng, /*sar*/ int * error_ret){LCL_FILE sec_stream;bits8_t *digest_ptr, *priv_ptr, *sec_buf;ALENGTH_T asn_length, asn_size, digest_length, priv_length;int asn_err = 0;sbits32_t mms, msg_boots, msg_time, lcl_time, lcl_boots;ENGINE_LEAF_T *engine = 0;SNMP_USER_T *user;#if INSTALL_ENVOY_SNMP_V3_NOTIFYSNMP_RETRANS_T *retrans;#endif/* decode the top level message sequence */if ((A_DecodeTypeClass(in_stream) != (A_UNIVERSAL | A_CONSTRUCTOR)) || (A_DecodeTypeValue(in_stream, &asn_err) != A_SEQUENCE)) asn_err = 1;asn_length = A_DecodeLength(in_stream, &asn_err);asn_size = Lcl_Size(in_stream);rp->msg_id = A_DecodeIntegerWTC(in_stream, &asn_err, A_INTEGER, A_UNIVERSAL | A_PRIMITIVE);mms = A_DecodeIntegerWTC(in_stream, &asn_err, A_INTEGER, A_UNIVERSAL | A_PRIMITIVE);rp->msg_flags = A_DecodeOctetWTC(in_stream, &asn_err, A_OCTETSTRING, A_UNIVERSAL | A_PRIMITIVE);rp->msg_sec_model = A_DecodeIntegerWTC(in_stream, &asn_err, A_INTEGER, A_UNIVERSAL | A_PRIMITIVE);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -