📄 ax_core.c
字号:
static void ax_search_list_encode(EBUFFER_T *ebuffp, bits8_t order, VBL_T *vblp, VB_T *vbp){VB_T *tempvbp;int i;if (vbp) { while(vbp) { ax_obj_id_encode(ebuffp, order, &vbp->vb_obj_id, vbp->ax_flags & ENVOY_AX_FLAGS_INCLUDE, 0); ax_obj_id_encode(ebuffp, order, &vbp->ax_search_end, 0, 0); vbp = vbp->vb_link; } }else { while(vblp) { for(i = vblp->vbl_count, tempvbp = vblp->vblist; i; i--, tempvbp++) { ax_obj_id_encode(ebuffp, order, &tempvbp->vb_obj_id, tempvbp->ax_flags & ENVOY_AX_FLAGS_INCLUDE, 0); ax_obj_id_encode(ebuffp, order, &tempvbp->ax_search_end, 0, 0); } vblp = vblp->vblp; } }}/********************************************************************************* envoy_ax_pkt_encode - encode a specified AgentX packet* SYNOPSIS** \cs* int envoy_ax_pkt_encode* ( * ENVOY_AX_PKT_T * ax_pkt, * VB_T * vbp, * EBUFFER_T * ebuffp, * ALENGTH_T need* )* \ce** DESCRIPTION** This routine attempts to encode a specified AgentX packet.** PARAMETERS* \is* \i <*ax_pkt>* Specify an AgentX packet.* \i <*vbp>* Specify the root of a linked list of 'VarBinds'. To use the 'VarBindList' * from the packet structure, set this value to 0.* \i <*ebuffp>* Point to an <ebuffp> structure that will be filled with the encoded packet. * The <ebuffp> may be a start pointer to an offset in this <ebuffp> or a next * pointer to another <ebuffp>. If no space is provided in the <ebuffp>, it is * the responsibility of the caller to free this space. You can use * SNMP_memory_alloc(), SNMP_memory_free() to allocate space in an <ebuffp>.* \i <need>* Specify the amount of space in bytes required for the encoded packet. To * automatically determine the required length, set this value to 0. Otherwise, * this routine assumes the input is correct.* \ie** RETURNS: If successful, this routine returns 0. Otherwise, it returns one of * the following error codes.* \is* \i 'ENVOY_AX_ALLOCATION_FAILURE'* Unable to allocate an AgentX packet.* \i 'ENVOY_AX_BAD_SIZE'* Insufficient space requested.* \i 'ENVOY_AX_BAD_VALUE'* The packet was badly formed or <ebuffp> did not match its expected size.* \i 'ENVOY_AX_TOO_SMALL'* The string is either smaller than the minimum PDU size or does not match the * expected length.* \ie** ERRNO: N/A** SEE ALSO: envoy_ax_pkt_decode(), SNMP_memory_alloc(), SNMP_memory_free()*/int envoy_ax_pkt_encode(ENVOY_AX_PKT_T *ax_pkt, VB_T *vbp, EBUFFER_T *ebuffp, ALENGTH_T need){bits8_t *bytes, order, range_id;/* figure out how much space we need and then see if we either have it or can get it */if (need == 0) { need = envoy_ax_pkt_size(ax_pkt, vbp); if (need == 0) return(ENVOY_AX_BAD_SIZE); }if (EBufferRemaining(ebuffp)) { /* we have some space, is it enough? */ if (EBufferRemaining(ebuffp) < need) return(ENVOY_AX_TOO_SMALL); }else { /* no space, allocate some and attach it to the ebuffer */ bytes = SNMP_memory_alloc(need); if (bytes == 0) return(ENVOY_AX_ALLOCATION_FAILURE); EBufferSetup(BFL_IS_DYNAMIC, ebuffp, bytes, need); }/* Get a pointer to the buffer string */bytes = EBufferNext(ebuffp);/* write the header of the packet and get the order flag info into a more easily used state */SET_AGENTX_PDU_VERSION(bytes, ax_pkt->version);SET_AGENTX_PDU_TYPE(bytes, ax_pkt->type);SET_AGENTX_PDU_FLAGS(bytes, ax_pkt->flags);bytes[3] = 0;if (ax_pkt->flags & ENVOY_AX_BIT_BYTE_ORDER) { order = 1; SET_AGENTX_PDU_SESSION_ID_B(bytes, ax_pkt->session_id); SET_AGENTX_PDU_TRANS_ID_B(bytes, ax_pkt->transaction_id); SET_AGENTX_PDU_PACKET_ID_B(bytes, ax_pkt->packet_id); SET_AGENTX_PDU_PAYLOAD_LEN_B(bytes, need - SIZEOF_AGENTX_PDU); }else { order = 0; SET_AGENTX_PDU_SESSION_ID_L(bytes, ax_pkt->session_id); SET_AGENTX_PDU_TRANS_ID_L(bytes, ax_pkt->transaction_id); SET_AGENTX_PDU_PACKET_ID_L(bytes, ax_pkt->packet_id); SET_AGENTX_PDU_PAYLOAD_LEN_L(bytes, need - SIZEOF_AGENTX_PDU); } (void) EBufferSeek(ebuffp, SIZEOF_AGENTX_PDU, 1);/* if necessary write the context */if (ax_pkt->flags & ENVOY_AX_BIT_NDC) ax_string_encode(ebuffp, order, &ax_pkt->context);/* then we write the pdu sections */bytes = EBufferNext(ebuffp);switch(ax_pkt->type) { default: return(ENVOY_AX_BAD_VALUE); case ENVOY_AX_OPEN: SET_AGENTX_OPEN_TIMEOUT(bytes, ax_pkt->data.open_data.timeout); bytes[1] = bytes[2] = bytes[3] = 0; (void) EBufferSeek(ebuffp, 4, 1); ax_obj_id_encode(ebuffp, order, &ax_pkt->data.open_data.sub_id, 0, 0); ax_string_encode(ebuffp, order, &ax_pkt->data.open_data.descr); break; case ENVOY_AX_CLOSE: SET_AGENTX_CLOSE_REASON(bytes, ax_pkt->data.reason); bytes[1] = bytes[2] = bytes[3] = 0; (void) EBufferSeek(ebuffp, SIZEOF_AGENTX_CLOSE, 1); break; case ENVOY_AX_REGISTER: case ENVOY_AX_UNREGISTER: SET_AGENTX_REG_TIMEOUT(bytes, ax_pkt->data.reg_data.timeout); SET_AGENTX_REG_PRIORITY(bytes, ax_pkt->data.reg_data.priority); range_id = ax_pkt->data.reg_data.range;#if INSTALL_ENVOY_AGENTX_2257_RANGE /* If we're behaving according to RFC2257, the range subid is relative to the start of the objectid in the packet, so if we have a range subid we may need to adjust it if we are also prefixing the objectid */ if (range_id && ax_is_prefix(&ax_pkt->data.reg_data.region, range_id)) range_id -= 5;#endif SET_AGENTX_REG_RANGE_SUBID(bytes, range_id); bytes[3] = 0; (void) EBufferSeek(ebuffp, 4, 1); ax_obj_id_encode(ebuffp, order, &ax_pkt->data.reg_data.region, 0, ax_pkt->data.reg_data.range); if (range_id) { bytes = EBufferNext(ebuffp); if (order) { GLUE_SB32((GLUE_CAST_PTR(bytes)), GLUE_CAST32(ax_pkt->data.reg_data.bound)); } else { GLUE_SL32((GLUE_CAST_PTR(bytes)), GLUE_CAST32(ax_pkt->data.reg_data.bound)); } (void) EBufferSeek(ebuffp, 4, 1); } break; case ENVOY_AX_GET: case ENVOY_AX_NEXT: /* we have a search list */ ax_search_list_encode(ebuffp, order, &ax_pkt->data.proc_data.vbl_str, vbp); break; case ENVOY_AX_BULK: if (order) { SET_AGENTX_BULK_NON_REP_B(bytes, ax_pkt->data.proc_data.non_reps); SET_AGENTX_BULK_MAX_REP_B(bytes, ax_pkt->data.proc_data.max_reps); } else { SET_AGENTX_BULK_NON_REP_L(bytes, ax_pkt->data.proc_data.non_reps); SET_AGENTX_BULK_MAX_REP_L(bytes, ax_pkt->data.proc_data.max_reps); } (void) EBufferSeek(ebuffp, SIZEOF_AGENTX_BULK, 1); ax_search_list_encode(ebuffp, order, &ax_pkt->data.proc_data.vbl_str, vbp); break; case ENVOY_AX_RESPONSE: if (order) { SET_AGENTX_RESP_SYS_UPTIME_B(bytes, ax_pkt->sysuptime); SET_AGENTX_RESP_ERROR_B(bytes, ax_pkt->error_stat); SET_AGENTX_RESP_INDEX_B(bytes, ax_pkt->error_index); } else { SET_AGENTX_RESP_SYS_UPTIME_L(bytes, ax_pkt->sysuptime); SET_AGENTX_RESP_ERROR_L(bytes, ax_pkt->error_stat); SET_AGENTX_RESP_INDEX_L(bytes, ax_pkt->error_index); } (void) EBufferSeek(ebuffp, SIZEOF_AGENTX_RESP, 1); ax_varbind_list_encode(ebuffp, order, &ax_pkt->data.proc_data.vbl_str, vbp); break; case ENVOY_AX_TEST: case ENVOY_AX_NOTIFY: case ENVOY_AX_INDEX_ALLOCATE: case ENVOY_AX_INDEX_DEALLOCATE: /* a varbind list */ ax_varbind_list_encode(ebuffp, order, &ax_pkt->data.proc_data.vbl_str, vbp); break; case ENVOY_AX_COMMIT: case ENVOY_AX_UNDO: case ENVOY_AX_CLEANUP: case ENVOY_AX_PING: /* just headers */ break; case ENVOY_AX_ADD_AC: /* a string and an oid */ ax_string_encode(ebuffp, order, &ax_pkt->data.open_data.descr); ax_obj_id_encode(ebuffp, order, &ax_pkt->data.open_data.sub_id, 0, 0); break; case ENVOY_AX_REMOVE_AC: /* an oid */ ax_obj_id_encode(ebuffp, order, &ax_pkt->data.open_data.sub_id, 0, 0); break; }return(0);}/****************************************************************************NAME: ax_obj_id_decodePURPOSE: Decode an object id, expanding any prefix informationPARAMETERS: EBUFFER_T * incoming packet bist8_t order byte bits8_t size check byte non-zero means don't read the data OBJ_ID_T * the object id to fill in bits8_t * the include bit RETURNS: int 0 on success, envoy_ax_error on error****************************************************************************/static int ax_obj_id_decode(EBUFFER_T *ebuffp, bits8_t order, bits8_t size_check, OBJ_ID_T *objid, bits8_t *inc){bits8_t *bytes;OIDC_T prefix, *subid;int num;bytes = EBufferNext(ebuffp);if (EBufferRemaining(ebuffp) < SIZEOF_AGENTX_OID) return(ENVOY_AX_TOO_SMALL);/* get the flags and adjust the byte string information */num = GET_AGENTX_OID_N_SUBID(bytes);prefix = GET_AGENTX_OID_PREFIX(bytes);*inc = GET_AGENTX_OID_INCLUDE(bytes);bytes += SIZEOF_AGENTX_OID;/* update the ebuffer info, we do it now before we trash num, we can do this because the deocding actually uses bytes. The seek function also has the side effect of testing that we have enough bytes left */if (EBufferSeek(ebuffp, SIZEOF_AGENTX_OID + (num * 4), 1)) return(ENVOY_AX_TOO_SMALL);if (size_check) return(0);/* set up the space for the object id list */if (prefix) objid->num_components = num + 5;else objid->num_components = num;if (objid->num_components == 0) { /* we're done */ return(0); }objid->component_list = SNMP_memory_alloc(objid->num_components * sizeof(OIDC_T));if (objid->component_list == 0) return(ENVOY_AX_ALLOCATION_FAILURE);/* now copy the information into the component list, adding the prefix if necessary */if (prefix) { MEMCPY(objid->component_list, ax_internet_prefix, 4 * sizeof(OIDC_T)); objid->component_list[4] = prefix; subid = &objid->component_list[5]; }else subid = objid->component_list;if (order) for(; num; num--, subid++, bytes += 4) { *subid = GLUE_GB32((GLUE_CAST_PTR(bytes))); }else for(; num; num--, subid++, bytes += 4) { *subid = GLUE_GL32((GLUE_CAST_PTR(bytes))); }return(0);}/****************************************************************************NAME: ax_string_decodePURPOSE: Decode a string, allocating space as necessary PARAMETERS: EBUFFER_T * the string to decode info from bits8_t the order flag bits8_t size check byte non-zero means don't read the data EBUFFER_T * where to put the stringRETURNS: int 0 on success, envoy_ax_errors on failure****************************************************************************/static int ax_string_decode(EBUFFER_T *ebuffp, bits8_t order, bits8_t size_check, EBUFFER_T *strbuf){bits8_t *bytes, *temp_bytes;bits32_t tlen; ALENGTH_T temp_len, pad_len;bytes = EBufferNext(ebuffp);if (EBufferRemaining(ebuffp) < SIZEOF_AGENTX_OCT_STR) return(ENVOY_AX_TOO_SMALL);/* get the length information */if (order) { tlen = GET_AGENTX_OCT_STR_LEN_B(bytes); }else { tlen = GET_AGENTX_OCT_STR_LEN_L(bytes); }if (tlen > MAX_ALENGTH) return(ENVOY_AX_TOO_BIG);temp_len = (ALENGTH_T)(tlen & MAX_ALENGTH);pad_len = temp_len%4;if (pad_len) pad_len = 4 - pad_len;/* update the ebuffer info, we can do this because the deocding actually uses bytes. The seek function also has the side effect of testing that we have enough bytes left */if (EBufferSeek(ebuffp, SIZEOF_AGENTX_OCT_STR + temp_len + pad_len, 1)) return(ENVOY_AX_TOO_SMALL);if (size_check) return(0);/* if we have a zero length string we are done */if (temp_len == 0) return(0);/* try to allocate space for the string */temp_bytes = SNMP_memory_alloc(temp_len);if (temp_bytes == 0) return(ENVOY_AX_ALLOCATION_FAILURE);/* copy the string and attach it to strbuf */MEMCPY(temp_bytes, PTR_AGENTX_OCT_STR_OCTETS(bytes), temp_len);EBufferPreLoad(BFL_IS_DYNAMIC, strbuf, temp_bytes, temp_len);return(0);}/****************************************************************************NAME: ax_varbind_decodePURPOSE: decode a varbindPARAMETERS: EBUFFER_T * the byte string to decode bits8_t the order flag bits8_t size check byte non-zero means don't read the data VB_T * varbind to hold the extracted infoRETURNS: int 0 on success, envoy_ax_errors on failure****************************************************************************/static int ax_varbind_decode(EBUFFER_T *ebuffp, bits8_t order, bits8_t size_check, VB_T *vbp){bits8_t *bytes, inc;int error_ret;bytes = EBufferNext(ebuffp);if (EBufferSeek(ebuffp, 4, 1)) return(ENVOY_AX_TOO_SMALL);if (order) { vbp->vb_data_flags_n_type = GET_AGENTX_VARBIND_TYPE_B(bytes); }else { vbp->vb_data_flags_n_type = GET_AGENTX_VARBIND_TYPE_L(bytes); }error_ret = ax_obj_id_decode(ebuffp, order, size_check, &vbp->vb_obj_id, &vbp->ax_flags);if (error_ret) return(error_ret);bytes = EBufferNext(ebuffp);switch(vbp->vb_data_flags_n_type) { default: return(ENVOY_AX_PARSE_ERROR); case VT_NUMBER:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -