📄 ax_sa.c
字号:
((vbp->vb_ml.ml_leaf)->getproc) (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_GET_STARTED; if (*err_stat) { for (vbp++, indx--; indx; indx--, vbp++) if (!(vbp->vb_flags & VFLAG_GET_STARTED)) vbp->vb_flags |= VFLAG_GET_STARTED | VFLAG_GET_DONE; envoy_ax_sa_next_continue(pktp); return; } } }for(indx = count, vbp = newvbp; indx; indx--, vbp++) if (vbp->vb_data_flags_n_type == VT_NOSUCHINS) { vbp->vb_flags &= ~(VFLAG_GET_STARTED | VFLAG_GET_DONE); vbp->vb_data_flags_n_type = VT_EMPTY; }/* Now we try to find any remaining varbinds using the next operation. We can reuse the mib leaf for those vbs for which a mib leaf was found in the above processing but the get routine wasn't able to find the desired instance, so while trying to find objects we skip any vbs that are either already started or already have a mib leaf. We have two var bind lists to help with error and status reporting so we need to make clones of object ids for any varbinds for which we try to find a next object and fail */for(indx = count, vbp = newvbp; indx && (*err_stat == 0); indx--, vbp++, oldvbp++) { if ((vbp->vb_flags & VFLAG_GET_STARTED) || (vbp->vb_ml.ml_flags & ML_IS_LEAF)) continue; /* 0 indicates that we couldn't find a next object so we tag it as end of mib. 1 indicates some sort of error when performing the lookup, we clean the object before processing in case we have an object left over from an attempted get*/ Clean_Obj_ID(&vbp->vb_obj_id); switch(find_next_object(vbp, &oldvbp->vb_obj_id, pktp, 0)) { case 0: if (clone_object_id(&oldvbp->vb_obj_id, &vbp->vb_obj_id)) { *err_stat = GEN_ERR; } vbp->vb_data_flags_n_type = VT_ENDOFMIB; vbp->vb_flags |= VFLAG_NEXT_STARTED | VFLAG_NEXT_DONE; break; case -1: *err_stat = GEN_ERR; break; } /* switch(find_next_object...) */ } /* for(indx = 0...) *//* if we had an error mark the vbs as done and bail out */if (*err_stat) { for (vbp = newvbp; count; count--, vbp++) if (!(vbp->vb_flags & VFLAG_NEXT_STARTED)) vbp->vb_flags |= VFLAG_NEXT_STARTED | VFLAG_NEXT_DONE; envoy_ax_sa_next_continue(pktp); return; }/* Loop through the vblist again and start all the nexts If the next started flag is set then we either set it above or the nextproc 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 call, if it is set we skip all the remaining vbs and mark them as done so we won't trip over them later. We don't mark the vb that caused the failure. */for(vbp = newvbp; count && *err_stat == 0; count--, vbp++) { if (vbp->vb_flags & (VFLAG_NEXT_STARTED | VFLAG_NEXT_DONE)) continue; ((vbp->vb_ml.ml_leaf)->nextproc) (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_NEXT_STARTED; if (*err_stat) { for (vbp++, count--; count; count--, vbp++) if (!(vbp->vb_flags & VFLAG_NEXT_STARTED)) vbp->vb_flags |= VFLAG_NEXT_STARTED | VFLAG_NEXT_DONE; break; } }envoy_ax_sa_next_continue(pktp);return;}/**************************************************************************NAME: envoy_ax_sa_test_continuePURPOSE: Continuation routine for test phase of a set request. We determine if all of the test routines have finished. If they have we cause a reply packet to be generated. If the packet had an error or if the master agent requested a cleanup we do so and perhaps start another operation.PARAMETERS: SNMP_PKT_T * The decoded set requestRETURNS: void****************************************************************************/static void envoy_ax_sa_test_continue(SNMP_PKT_T *pktp){VB_T *vbp;int count, err_status = 0;ENVOY_AX_PKT_T **tax_pktp, *ax_pkt;ENVOY_AX_SA_SB_T *sasb;VBL_T vblp;if (pktp->phase != VFLAG_TEST_DONE) { /* get some initial information */ 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_TEST_DONE)) {#if (INSTALL_ENVOY_CONTINUE_REENTRANT) ENVOY_SNMP_RELEASE_WRITE_LOCK(pktp->continue_lock);#endif return; } }#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));ax_pkt = pktp->ax_pkt;sasb = 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_test_continue(): list lock is broken", 0)); return; }#endif/* work out the next phase of the processing and set the timestamp if necessary */ax_pkt->ts = ENVOY_NOW();if (pktp->pdu.std_pdu.error_status || (ax_pkt->data.proc_data.next_phase == ENVOY_AX_NEXT_CLEANUP_START) || envoy_tm_set(&sasb->ager, envoy_ax_sa_timeout)) { err_status = 1; /* remove the request from the list */ for (tax_pktp = &sasb->set_list; *tax_pktp; tax_pktp = &(*tax_pktp)->next) if (*tax_pktp == ax_pkt) { *tax_pktp = ax_pkt->next; break; } }else { ax_pkt->data.proc_data.cur_phase = VFLAG_TEST_DONE; sasb->flags = 1; }ENVOY_SNMP_RELEASE_WRITE_LOCK(sasb->list_lock);/* err_status will be set if a test failed or if the master requested that we cleanup this message, if necessary we tell the user we are bailing out then cleanup. As part of the cleanup we check the next phase comp routines and, if it exists, run the error one. Then if serialization is turned on we need to start the next request. */if (err_status) {#if defined(SNMP_user_set_failed) SNMP_user_set_failed(pktp);#endif envoy_ax_pkt_free(ax_pkt); SNMP_Free(pktp);#if (INSTALL_ENVOY_SNMP_SERIALIZE) (void) envoy_tm_set(&sasb->defer, 0);#endif /* (INSTALL_ENVOY_SNMP_SERIALIZE) */ }return;}/****************************************************************************\NOMANUALNAME: envoy_ax_sa_test_pduPURPOSE: Start the processing of a test request. First we try to find objects for all of the var binds. If any of the var binds don't lead to a useable object we flag an error, otherwise we try to start the test routines for all the objects. If we detect an error while doing this we mark the reminaing objects as having been processed and call the continue routine to cleanup.PARAMETERS: SNMP_PKT_T * The decoded SET PDURETURNS: void****************************************************************************/void envoy_ax_sa_test_pdu(SNMP_PKT_T *pktp){VB_T *vbp;int count, indx;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 */*err_stat = NO_ERROR;pktp->pdu.std_pdu.error_index = 0;pktp->cont = envoy_ax_sa_test_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_TEST_DONE; envoy_ax_sa_test_continue(pktp); return; }/* try to find the object for the given var bind and test it to see if we can write to it */for(indx = 0; indx < count; indx++,vbp++) { switch(find_object_node(vbp, pktp, 0)) { case 0: break; case -1: default: testproc_error(pktp, vbp, NOT_WRITABLE); pktp->phase = VFLAG_TEST_DONE; envoy_ax_sa_test_continue(pktp); return; case -2: testproc_error(pktp, vbp, NO_ACCESS); pktp->phase = VFLAG_TEST_DONE; envoy_ax_sa_test_continue(pktp); return; } /* Check the returned node, it must be a leaf node and the mib must allow writes */ if ((!(vbp->vb_ml.ml_flags & ML_IS_LEAF)) || (!((vbp->vb_ml.ml_leaf)->access_type & WRITE_ACCESS))) { testproc_error(pktp, vbp, NOT_WRITABLE); pktp->phase = VFLAG_TEST_DONE; envoy_ax_sa_test_continue(pktp); return; } /* Finally see if the vb's data type matches the node's type */ if (vbp->vb_data_flags_n_type != (vbp->vb_ml.ml_leaf)->expected_tag) { testproc_error(pktp, vbp, WRONG_TYPE); pktp->phase = VFLAG_TEST_DONE; envoy_ax_sa_test_continue(pktp); return; } }/* Here we give the user a chance to examine the packet and exert control They have three options: Return -1 to indicate an inconsistent pdu, an error will be generated Return 0 to inidcate that normal processing should proceed, the user must not perform any sets though it may perfrom tests. Reurn 1 to indicate that it has performed all necessary processing. this last option is not available in sub agents */#if defined(SNMP_validate_set_pdu)switch(SNMP_validate_set_pdu(pktp)) { case 1: default: /* these options are not available in a sub agent, instead we generate an error message. */ case -1: *err_stat = GEN_ERR; pktp->phase = VFLAG_TEST_DONE; envoy_ax_sa_test_continue(pktp); return; case 0: break; }#endif/* We have found all of the requested objects and passed all the mib type tests. We try to start the tests. If a test started flag is set then we either set it above or the testproc 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 tested (so we won't trip over them later). We skip the vb that cause the error. */for(vbp = pktp->pdu.std_pdu.std_vbl.vblist; count; count--, vbp++) { if (vbp->vb_flags & (VFLAG_TEST_STARTED | VFLAG_TEST_DONE)) continue; ((vbp->vb_ml.ml_leaf)->testproc) (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_TEST_STARTED; if (*err_stat) { for (vbp++, count--; count; count--, vbp++) if (!(vbp->vb_flags & VFLAG_TEST_STARTED)) vbp->vb_flags |= VFLAG_TEST_STARTED | VFLAG_TEST_DONE; break; } }envoy_ax_sa_test_continue(pktp);}/**************************************************************************NAME: envoy_ax_sa_set_continuePURPOSE: Continuation routine for commit phase of a set request. We determine if all of the set routines have finished. If they have we cause a reply packet to be generated. If the master agent requested it we try to undo the setPARAMETERS: SNMP_PKT_T * The decoded partially processed set requestRETURNS: void****************************************************************************/static void envoy_ax_sa_set_continue(SNMP_PKT_T *pktp){VB_T *vbp;VBL_T vblp;int count, undo_status = 0;ENVOY_AX_PKT_T *ax_pkt;if (pktp->phase != VFLAG_SET_DONE) { /* get some initial information */ 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_SET_DONE)) {#if (INSTALL_ENVOY_CONTINUE_REENTRANT) ENVOY_SNMP_RELEASE_WRITE_LOCK(pktp->continue_lock);#endif return; } }#if defined(SNMP_user_post_set)/* The user gets another chance to examine the packet and exert control. */SNMP_user_post_set(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));ax_pkt = pktp->ax_pkt;#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(ax_pkt->sasb->list_lock)) { BUG(BUG_ENVOY_LOCKING, BUG_FATAL, 0, (BUG_OUT, "envoy_ax_sa_set_continue(): list lock is broken", 0)); return; }#endif/* work out the next phase of the processing and set the timestamp if necessary */ax_pkt->ts = ENVOY_NOW();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -