📄 ax_sa.c
字号:
if ((ax_pkt->data.proc_data.next_phase == ENVOY_AX_NEXT_UNDO_START) || envoy_tm_set(&ax_pkt->sasb->ager, envoy_ax_sa_timeout)) { undo_status = 1; ax_pkt->data.proc_data.cur_phase = VFLAG_UNDO_STARTED; ax_pkt->send = ax_pkt->data.proc_data.next_send; ax_pkt->error = ax_pkt->data.proc_data.next_error; ax_pkt->cookie = ax_pkt->data.proc_data.next_cookie; }else { pktp->ax_pkt->data.proc_data.cur_phase = VFLAG_SET_DONE; ax_pkt->sasb->flags = 1; }ENVOY_SNMP_RELEASE_WRITE_LOCK(ax_pkt->sasb->list_lock);/* undo_status will be set if the master requested an undo */if (undo_status) {#if (INSTALL_ENVOY_CONTINUE_REENTRANT) /* If necessary we acquire the packet continue write lock here It gets freed when we call the continue routine. We don't have any good options if we can't get the lock. The user shouldn't do that, if they do we generate a bug report and if they don't handle that we return which is the least bad thing to do. */ if (ENVOY_SNMP_GET_WRITE_LOCK(pktp->continue_lock)) { BUG(BUG_ENVOY_LOCKING, BUG_FATAL, 0, (BUG_OUT, "envoy_ax_sa_set_continue(): packet continue lock is broken", 0)); return; }#endif envoy_ax_sa_undo_pdu(pktp); }}/****************************************************************************NAME: envoy_ax_sa_set_pduPURPOSE: Start the processing of a set (commit) request. The test phase has already found all of the objects so basically we just call routines to perform the sets.PARAMETERS: SNMP_PKT_T * The decoded partially process set requestRETURNS:****************************************************************************/static void envoy_ax_sa_set_pdu(SNMP_PKT_T *pktp){VB_T *vbp;int count;INT_32_T *err_stat;/* We will be looking at the error status a lot so we get a local pointer to it to make things easier */err_stat = &(pktp->pdu.std_pdu.error_status);/* assume that things are going to work */pktp->cont = envoy_ax_sa_set_continue;/* get some initial information */if (((vbp = pktp->pdu.std_pdu.std_vbl.vblist) == 0) || ((count = pktp->pdu.std_pdu.std_vbl.vbl_count) == 0)) { pktp->phase = VFLAG_SET_DONE; envoy_ax_sa_set_continue(pktp); return; }/* The user gets another chance to examine the packet and exert control. They again have three options: -1 indicates a bad pdu, an error will be generated 0 inidcates normal processing should proceed, the user may start or perfrom any sets they desire. But they better indicate what they have done. If the user has started some sets and one of them fails they may either wait until they all finish and return a -1 or 1, or they way set the flag bits for the other vbs to be already set & undone and then let this code wait for the remaining tests to finish. They also have to set the err status correctly. 1 indicates the user has performed all necessary processing */#if defined(SNMP_user_pre_set)switch(SNMP_user_pre_set(pktp)) { case 0: break; case -1: /* set the error then drop into the next case */ *err_stat = GEN_ERR; case 1: default: pktp->phase = VFLAG_SET_DONE; envoy_ax_sa_set_continue(pktp); return; }#endif/* Start up the sets. If a set started flag is set then we either set it above or the testproc or setproc of some other var bind has claimed responsibility for it. In either case we skip the var bind and continue. We also test the error code after each varbind, if we had an error then we mark any remaining vbs as having been set (so we won't trip over them later). We skip the vb that cause the error. */for(; count; count--, vbp++) { if (vbp->vb_flags & (VFLAG_SET_STARTED | VFLAG_SET_DONE)) continue; ((vbp->vb_ml.ml_leaf)->setproc) (vbp->vb_ml.ml_last_match, vbp->vb_ml.ml_remaining_objid.num_components, vbp->vb_ml.ml_remaining_objid.component_list, pktp, vbp); vbp->vb_flags |= VFLAG_SET_STARTED; if (*err_stat) { for (vbp++, count--; count; count--, vbp++) if (!(vbp->vb_flags & VFLAG_SET_STARTED)) vbp->vb_flags |= VFLAG_SET_STARTED | VFLAG_SET_DONE | VFLAG_UNDO_STARTED | VFLAG_UNDO_DONE; *err_stat = COMMIT_FAILED; break; } }envoy_ax_sa_set_continue(pktp);}/****************************************************************************NAME: envoy_ax_sa_undo_continuePURPOSE: The continuation routine for processing an undo request Basically we just wait for all the undos to finish and then cleanup the state.PARAMETERS: SNMP_PKT_T * The decoded and partially processed set requestRETURNS: void****************************************************************************/static void envoy_ax_sa_undo_continue(SNMP_PKT_T *pktp){VB_T *vbp;int count;ENVOY_AX_PKT_T **tax_pktp;ENVOY_AX_SA_SB_T *sasb;VBL_T vblp;/* Test to see if all of the undos have finished yet */if (pktp->phase != VFLAG_UNDO_DONE) { vbp = pktp->pdu.std_pdu.std_vbl.vblist; count = pktp->pdu.std_pdu.std_vbl.vbl_count; for (; count; count--, vbp++) { if (!(vbp->vb_flags & VFLAG_UNDO_DONE)) {#if (INSTALL_ENVOY_CONTINUE_REENTRANT) ENVOY_SNMP_RELEASE_WRITE_LOCK(pktp->continue_lock);#endif return; } } }/* Here we tell the user that one of sets failed, this gives them a chance to clean up, perhaps after user_pre_set */#if defined(SNMP_user_set_failed)SNMP_user_set_failed(pktp);#endif#if (INSTALL_ENVOY_CONTINUE_REENTRANT)ENVOY_SNMP_RELEASE_WRITE_LOCK(pktp->continue_lock);#endif/* send the reply */MEMCPY(&vblp, &pktp->pdu.std_pdu.std_vbl, sizeof(VBL_T));MEMSET(&pktp->pdu.std_pdu.std_vbl, 0, sizeof(VBL_T)); (void) envoy_ax_sa_reply(pktp, pktp->ax_pkt);MEMCPY(&pktp->pdu.std_pdu.std_vbl, &vblp, sizeof(VBL_T));sasb = pktp->ax_pkt->sasb;#if INSTALL_ENVOY_SNMP_LOCK/* We don't have any good options if we can't get the lock. So we require the user to not do that, if they do we generate a bug report and if they don't handle that we return which is the least bad thing to do. */if (ENVOY_SNMP_GET_WRITE_LOCK(sasb->list_lock)) { BUG(BUG_ENVOY_LOCKING, BUG_FATAL, 0, (BUG_OUT, "envoy_ax_sa_undo_continue(): agentx sub agent list lock is broken", 0)); return; }#endif/* remove the request from the list */for (tax_pktp = &sasb->set_list; *tax_pktp; tax_pktp = &(*tax_pktp)->next) if (*tax_pktp == pktp->ax_pkt) { *tax_pktp = pktp->ax_pkt->next; break; }/* cancel the timer */if (sasb->flags) { sasb->flags = 0; (void) envoy_tm_cancel(&sasb->ager); }ENVOY_SNMP_RELEASE_WRITE_LOCK(sasb->list_lock);envoy_ax_pkt_free(pktp->ax_pkt);SNMP_Free(pktp);#if (INSTALL_ENVOY_SNMP_SERIALIZE) (void) envoy_tm_set(&sasb->defer, 0);#endif /* (INSTALL_ENVOY_SNMP_SERIALIZE) */}/****************************************************************************\NOMANUALNAME: envoy_ax_sa_undo_pduPURPOSE: Start the processing of an undo request. The set routines may or may not have set up an undo routine, so we step through the list looking for varbinds we need to undo and then see if they actually have a routine.PARAMETERS: SNMP_PKT_T * The decoded and partially processed set requestRETURNS: void****************************************************************************/void envoy_ax_sa_undo_pdu(SNMP_PKT_T *pktp){VB_T *vbp;int count;/* assume that things are going to work */pktp->cont = envoy_ax_sa_undo_continue;/* get some initial information */if (((vbp = pktp->pdu.std_pdu.std_vbl.vblist) == 0) || ((count = pktp->pdu.std_pdu.std_vbl.vbl_count) == 0)) { pktp->phase = VFLAG_UNDO_DONE; envoy_ax_sa_undo_continue(pktp); return; }/* Start up the undos. If an undo started flag is set then we either set it above or the testproc, setproc or undoproc of some other var bind has claimed responsibility for it. In either case we skip the var bind and continue. */for(; count; count--, vbp++) { if (!(vbp->vb_flags & VFLAG_UNDO_STARTED)) { if (vbp->undoproc) { (vbp->undoproc)(vbp->vb_ml.ml_last_match, vbp->vb_ml.ml_remaining_objid.num_components, vbp->vb_ml.ml_remaining_objid.component_list, pktp, vbp); vbp->vb_flags |= VFLAG_UNDO_STARTED; } else { pktp->pdu.std_pdu.error_status = UNDO_FAILED; vbp->vb_flags |= VFLAG_UNDO_STARTED | VFLAG_UNDO_DONE; } } }envoy_ax_sa_undo_continue(pktp);}/****************************************************************************NAME: pre_process_pduPURPOSE: some common setup code for the different pdu types we try to allocate the snmp packet and fill in various information, then get the per packet continue lock NOTE: we put a copy of the context info into the snmp packet structure and mark it as static, this will work as long as the snmp packet is not used after the agentx structure is freed. This is currently the case, if it changes update this code.PARAMETERS: RETURNS: ****************************************************************************/static int pre_process_pdu(ENVOY_AX_PKT_T *ax_pkt){SNMP_PKT_T *pktp;int mib_flag;bits8_t ax_type;/* allocate the snmp packet and start filling it in */pktp = SNMP_Allocate();if (pktp) { /* try to get a mib tree for this agent with the specified context, if we succeed we continue filling in the snmp packet struct and zero out the data in the ax struct to avoid accidents. if we fail we get rid of the snmp packet */ mib_flag = ENVOY_AX_SA_MIB_ROOT_NODE(ax_pkt->cookie, pktp); if (mib_flag == 0) { pktp->snmp_version = SNMP_VERSION_2; EBufferPreLoad(BFL_IS_STATIC, &pktp->community, EBufferStart(&ax_pkt->context), EBufferUsed(&ax_pkt->context)); pktp->pdu.std_pdu.std_vbl.vblist = ax_pkt->data.proc_data.vbl_str.vblist; pktp->pdu.std_pdu.std_vbl.vbl_count = ax_pkt->data.proc_data.vbl_str.vbl_count; ax_pkt->data.proc_data.vbl_str.vblist = 0; ax_pkt->data.proc_data.vbl_str.vbl_count = 0; ax_pkt->pktp = pktp; pktp->ax_pkt = ax_pkt;#if (INSTALL_ENVOY_CONTINUE_REENTRANT) if (ENVOY_SNMP_GET_WRITE_LOCK(pktp->continue_lock) == 0) return(0); else { BUG(BUG_ENVOY_LOCKING, BUG_CONTINUABLE, 0, (BUG_OUT, "pre_process_pdu: continue lock is broken", 0)); }#else return(0);#endif } SNMP_Free(pktp); }/* we had some sort of error, send back a gen err and bail out, we clean up the vb list first as we don't need to send it back */Clean_vb_list(&ax_pkt->data.proc_data.vbl_str);ax_pkt->data.proc_data.vbl_str.vblist = 0;ax_pkt->data.proc_data.vbl_str.vbl_count = 0;ax_pkt->error_stat = GEN_ERR;ax_type = ax_pkt->type;ax_pkt->type = ENVOY_AX_RESPONSE; (void) ax_pkt->send(ax_pkt->cookie, ax_pkt, 0, envoy_ax_pkt_size(ax_pkt, 0));ax_pkt->type = ax_type;envoy_ax_pkt_free(ax_pkt);return(1);}/********************************************************************************* envoy_ax_sa_handler - process packets for AgentX subagents* SYNOPSIS** \cs* void envoy_ax_sa_handler* ( * bits8_t * pkt_str, * ALENGTH_T pkt_len, * ENVOY_AX_SA_SB_T * sasb, * ENVOY_AX_ADMIN_T * admin_rtn, * ENVOY_AX_SEND_T * send_rtn, * ENVOY_AX_ERROR_T * err_rtn, * ptr_t send_cookie * )* \ce** DESCRIPTION** This routine is the main processing routine for an AgentX subagent. If you * are processing packets received from TCP or any other streams-based transport * protocol, use envoy_ax_chunk_handler().** PARAMETERS* \is* \i <*pkt_str>* Specify the packet to be processed.* \i <pkt_len>* Specify the length in bytes of the packet to be processed.* \i <*sasb>* Specify the subagent state block associated with this subagent.* \i <*admin_rtn>* Specify a customer-provided routine that is called when an 'OPEN' PDU * establishes that the session is open or when an AgentX 'TRAP' PDU is * received.* \i <*error_rtn>* Specify a customer-provided routine that is called to respond to errors.* \i <*send_rtn>* Specify a customer-provided routine that is called to send packets.* \i <send_cookie>* Specify the cookie, which would contain an address for UDP or a pointer to a * TCP block.* \ie** RETURNS: None.** ERRNO: N/A** SEE ALSO: envoy_ax_chunk_handler(), envoy_ax_ma_handler(), * envoy_ax_sa_state_create(), envoy_ax_sa_state_init(),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -