📄 ax_sa.c
字号:
* Indicate whether to remove operations for only this session (0) or for all * sessions (1) for this connection specified by <cookie>.* \i <session_id>* Specify the session id.* \ie** RETURNS: If successful, this routine returns 0. Otherwise, it returns 1. * Failures are often associated with problems with the locking code.** ERRNO: N/A** SEE ALSO: 'ENVOY_AX_COOKIE_CMP(),' envoy_ax_ma_cleanup_sessions(), * envoy_ax_sa_state_create(), envoy_ax_sa_handler(), envoy_ax_sa_state_init(), * 'ENVOY_AX_SA_MIB_ROOT_NODE()'*/int envoy_ax_sa_session_loss(ENVOY_AX_SA_SB_T *sasb, ptr_t cookie, int sflag, bits32_t session_id){ENVOY_AX_PKT_T *ax_pkt, **ax_pktp, *set_pkt = 0;#if INSTALL_ENVOY_SNMP_LOCKif (ENVOY_SNMP_GET_WRITE_LOCK(sasb->list_lock)) { BUG(BUG_ENVOY_LOCKING, BUG_CONTINUABLE, 0, (BUG_OUT, "envoy_ax_sa_session_loss: list lock is broken", 0)); return(-1); }#endif/* first we get rid of any gnb ops for this transport */ax_pktp = &sasb->gnb_list;while (*ax_pktp) { if ((ENVOY_AX_COOKIE_CMP((*ax_pktp)->cookie, cookie)) && (sflag || ((*ax_pktp)->session_id == session_id))) { ax_pkt = *ax_pktp; *ax_pktp = ax_pkt->next; ax_pkt->error(ax_pkt->cookie, ENVOY_AX_SESS_LOSS); ax_pkt->error = 0; SNMP_Free(ax_pkt->pktp); envoy_ax_pkt_free(ax_pkt); } else ax_pktp = &(*ax_pktp)->next; }/* next do the sets */ax_pktp = &sasb->set_list;while (*ax_pktp) { if ((ENVOY_AX_COOKIE_CMP((*ax_pktp)->cookie, cookie)) && (sflag || ((*ax_pktp)->session_id == session_id))) { switch((*ax_pktp)->data.proc_data.cur_phase) { case 0: /* We haven't started the tests yet, we just need to cleanup the packets and tell the user that we are done with the packet */ ax_pkt = *ax_pktp; *ax_pktp = ax_pkt->next; ax_pkt->error(ax_pkt->cookie, ENVOY_AX_SESS_LOSS); ax_pkt->error = 0; SNMP_Free(ax_pkt->pktp); envoy_ax_pkt_free(ax_pkt); break; case VFLAG_TEST_STARTED: /* we've started the tests tag it as needing to be cleaned */ (*ax_pktp)->data.proc_data.next_phase = ENVOY_AX_NEXT_CLEANUP_START; break; case VFLAG_TEST_DONE: /* we already finished the tests, unhook the packet from the list, it will be cleaned later after we release the list lock */ set_pkt = *ax_pktp; *ax_pktp = set_pkt->next; break; case VFLAG_SET_STARTED: /* we've started the sets tag it as needing to be undone */ (*ax_pktp)->data.proc_data.next_phase = ENVOY_AX_NEXT_UNDO_START; break; case VFLAG_SET_DONE: /* we've finished the sets, try to undo them */ set_pkt = *ax_pktp; (*ax_pktp)->data.proc_data.cur_phase = VFLAG_UNDO_STARTED; break; /* An undo is already in progress, the packet is already being cleaned up */ case VFLAG_UNDO_STARTED: break; } } else ax_pktp = &(*ax_pktp)->next; }ENVOY_SNMP_RELEASE_WRITE_LOCK(sasb->list_lock);if (set_pkt) { if (set_pkt->data.proc_data.cur_phase == VFLAG_TEST_DONE) { set_pkt->error(set_pkt->cookie, ENVOY_AX_SESS_LOSS); set_pkt->error = 0; SNMP_Free(set_pkt->pktp); envoy_ax_pkt_free(set_pkt); } else {#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(set_pkt->pktp->continue_lock)) { BUG(BUG_ENVOY_LOCKING, BUG_FATAL, 0, (BUG_OUT, "envoy_ax_sa_session_loss(): packet continue lock is broken", 0)); return(0); }#endif envoy_ax_sa_undo_pdu(set_pkt->pktp); return(0); } }#if (INSTALL_ENVOY_SNMP_SERIALIZE) (void) envoy_tm_set(&sasb->defer, 0);#endif /* (INSTALL_ENVOY_SNMP_SERIALIZE) */return(0);}/****************************************************************************NAME: envoy_ax_sa_replyPURPOSE: call the completion routine to send a packetPARAMETERS: SNMP_PKT_T * ENVOY_AX_PKT_T *RETURNS: int 0 on success****************************************************************************/static int envoy_ax_sa_reply(SNMP_PKT_T *pktp, ENVOY_AX_PKT_T *ax_pkt){ax_pkt->type = ENVOY_AX_RESPONSE;ax_pkt->error_stat = (bits16_t)pktp->pdu.std_pdu.error_status & 0xFFFF;ax_pkt->error_index = (bits16_t)pktp->pdu.std_pdu.error_index & 0xFFFF;if (ax_pkt->error_stat == 0) { ax_pkt->data.proc_data.vbl_str.vblist = pktp->pdu.std_pdu.std_vbl.vblist; ax_pkt->data.proc_data.vbl_str.vbl_count = pktp->pdu.std_pdu.std_vbl.vbl_count; ax_pkt->data.proc_data.vbl_str.vblp = pktp->pdu.std_pdu.std_vbl.vblp; } (void) ax_pkt->send(ax_pkt->cookie, ax_pkt, 0, envoy_ax_pkt_size(ax_pkt, 0));ax_pkt->data.proc_data.vbl_str.vblist = 0;ax_pkt->data.proc_data.vbl_str.vbl_count = 0;ax_pkt->data.proc_data.vbl_str.vblp = 0;return(0);}/****************************************************************************NAME: envoy_ax_sa_get_continuePURPOSE: Determine if all the gets associated with the packet have finished. If they haven't we release the continue lock and return. Otherwise we try to send back a reply and cleanup the packet. Finally if we are in serialization mode we update the serial stats and try to start other requests.PARAMETERS: SNMP_PKT_T * The decoded GET PDURETURNS: void****************************************************************************/static void envoy_ax_sa_get_continue(SNMP_PKT_T *pktp){VB_T *vbp;int count;#if (INSTALL_ENVOY_SNMP_SERIALIZE)ENVOY_AX_SA_SB_T *sasb = pktp->ax_pkt->sasb;#endif /* (INSTALL_ENVOY_SNMP_SERIALIZE) */if (pktp->phase != VFLAG_GET_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_GET_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 */ (void) envoy_ax_sa_reply(pktp, pktp->ax_pkt);envoy_ax_pkt_free(pktp->ax_pkt);SNMP_Free(pktp);#if (INSTALL_ENVOY_SNMP_SERIALIZE)sasb->readers--; (void) envoy_tm_set(&sasb->defer, 0);#endif /* (INSTALL_ENVOY_SNMP_SERIALIZE) */return;}/****************************************************************************\NOMANUALNAME: envoy_ax_sa_get_pduPURPOSE: Find the requested objects, and try to start all the routines associated with them. We call envoy_ax_sa_continue at the end to see if all of the gets have already succeeded it will handled any response and cleanup that is required.PARAMETERS: SNMP_PKT_T * The decoded GET PDURETURNS: void****************************************************************************/void envoy_ax_sa_get_pdu(SNMP_PKT_T *pktp){VB_T *vbp, *vbplist;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 everything will work */*err_stat = NO_ERROR;pktp->pdu.std_pdu.error_index = 0;pktp->cont = envoy_ax_sa_get_continue;vbplist = pktp->pdu.std_pdu.std_vbl.vblist;count = pktp->pdu.std_pdu.std_vbl.vbl_count;/* get some initial information */if ((vbplist == 0) || (count == 0)) { pktp->phase = VFLAG_GET_DONE; envoy_ax_sa_get_continue(pktp); }/* Attempt to find all the requested objects, if we can't find an object or it isn't readable we set it to a NO_SUCH_OBJECT exception, tag the vbp as done and continue with the rest */for(indx = count, vbp = vbplist; indx; indx--, vbp++) { if ((find_object_node(vbp, pktp, 0) != 0) || ((vbp->vb_ml.ml_flags & ML_IS_LEAF) == 0) || (((vbp->vb_ml.ml_leaf)->access_type & READ_ACCESS) == 0)) { vbp->vb_data_flags_n_type = VT_NOSUCHOBJ; vbp->vb_flags |= VFLAG_GET_STARTED | VFLAG_GET_DONE; } /* if ((find_object...) */ } /* for(indx = 0...) *//* Now we loop through the vblist again and start all the gets. If a get started flag is set then we either set it above or the getproc 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(indx = count, vbp = vbplist; indx; indx--, vbp++) { if (vbp->vb_flags & (VFLAG_GET_STARTED | VFLAG_GET_DONE)) continue; ((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; break; } }envoy_ax_sa_get_continue(pktp);}/****************************************************************************NAME: envoy_ax_sa_next_redoPURPOSE: Continuation of next/bulk processing. This routine is responsible for looking over the varbind list and, for varbinds that have no such instance exceptions (indicating that we performed a get on them - due to the include bit) starting a nextproc, for varbinds that have the redo flag set we need to find the next object and try its nextproc.PARAMETERS: SNMP_PKT_T * the partially processed next/bulk pduRETURNS: int 0 this stage of processing is finished continue onward. -1 error, we also set the phase word to next_done 1 Several nextprocs were restarted we need to redo this stage****************************************************************************/static int envoy_ax_sa_next_redo(SNMP_PKT_T *pktp){VBL_T *vblp;VB_T *vbp, *tvbp, *oldvbp, *orgvbp;int count, indx;OBJ_ID_T target;int restart_flag = 0, temp_restart_flag;/* Get some initial information. We need to determine which var bind list to use. Nexts have only one but bulks may have several chained together. We want the last one as it will be the only one with variables that may need to be redone. We also get a pointer to the object list as the base for this round. We will need this pointer in the case of a v2 end of mib exception as we are suppossed to send back the object we attempted a next from. */vblp = &(pktp->pdu.std_pdu.std_vbl);if (vblp->vblp == 0) oldvbp = pktp->pdu.std_pdu.saved_vbl.vblist;else for(oldvbp = vblp->vblist + pktp->pdu.std_pdu.non_reps, vblp = vblp->vblp; vblp->vblp; oldvbp = vblp->vblist, vblp = vblp->vblp) ;if (((vbp = vblp->vblist) == 0) || ((count = vblp->vbl_count) == 0)) return(0);/* get a pointer to the section of the original vbp list so we can check on the end of search range */if (vblp == &(pktp->pdu.std_pdu.std_vbl)) orgvbp = pktp->pdu.std_pdu.saved_vbl.vblist;else orgvbp = pktp->pdu.std_pdu.saved_vbl.vblist + pktp->pdu.std_pdu.non_reps;/* loop through the varbind list figuring out which varbinds we need to redo. varbinds that have a no such instance exception are gets (from the include bit) that failed, we reset the started and done bits and use the nextproc from the current mib leaf. varbinds that have a redo flag set are more complicated. we need to find the next object for them as well as resetting the flags. lastly we need to check that any varbinds that have completed or new objects we just found are within the search range. any that are out of range are cleaned and tagged with an end of mib indicator. */for(tvbp = vbp, indx = 0; indx < count; tvbp++, indx++, orgvbp++) { if (tvbp->vb_data_flags_n_type == VT_NOSUCHINS) { restart_flag = 1; tvbp->vb_flags &= ~(VFLAG_NEXT_FLAGS | VFLAG_GET_DONE); tvbp->vb_data_flags_n_type = VT_EMPTY; continue; } temp_restart_flag = 0; if (tvbp->vb_flags & VFLAG_NEXT_REDO) { /* Redo is required, next proc was unable to find anything, go to next obj. Chop off any instance qualifier and increment the last subid of the object id */ target.num_components = tvbp->vb_obj_id.num_components - tvbp->vb_ml.ml_remaining_objid.num_components; target.component_list = tvbp->vb_obj_id.component_list; target.component_list[target.num_components-1]++; tvbp->vb_obj_id.component_list = 0; tvbp->vb_obj_id.num_components = 0; tvbp->vb_flags &= ~VFLAG_NEXT_FLAGS; /* 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 */ switch(find_next_object(tvbp, &target, pktp, 0)) { case 0: if (clone_object_id((&(oldvbp + indx)->vb_obj_id), &tvbp->vb_obj_id)) { Clean_Obj_ID(&target); pktp->pdu.std_pdu.error_status = GEN_ERR; pktp->phase = VFLAG_NEXT_DONE; return(-1); } tvbp->vb_data_flags_n_type = VT_ENDOFMIB; tvbp->vb_flags |= VFLAG_NEXT_STARTED | VFLAG_NEXT_DONE; break; case -1:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -