📄 ax_sa.c
字号:
Clean_Obj_ID(&target); pktp->pdu.std_pdu.error_status = GEN_ERR; pktp->phase = VFLAG_NEXT_DONE; return(-1); default: temp_restart_flag = 1; break; } /* switch(find_next_object...) */ Clean_Obj_ID(&target); } if ((orgvbp->ax_search_end.num_components) && (oidcmp2(orgvbp->ax_search_end.num_components, orgvbp->ax_search_end.component_list, tvbp->vb_obj_id.num_components, tvbp->vb_obj_id.component_list) <= 0)) { Clean_vb(tvbp); tvbp->vb_data_flags_n_type = VT_ENDOFMIB; tvbp->vb_flags |= VFLAG_NEXT_STARTED | VFLAG_NEXT_DONE; temp_restart_flag = 0; if (clone_object_id((&orgvbp->vb_obj_id), &tvbp->vb_obj_id)) { pktp->pdu.std_pdu.error_status = GEN_ERR; pktp->phase = VFLAG_NEXT_DONE; return(-1); } } if (temp_restart_flag) restart_flag = 1; } /* for(tvbp = vbp, indx = 0; indx < count; tvbp++, indx++) { *//* If necessary we 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 */if (restart_flag) { for(indx = 0, tvbp = vbp; indx < count; indx++, tvbp++) { if (tvbp->vb_flags & (VFLAG_NEXT_STARTED | VFLAG_NEXT_DONE)) continue; ((tvbp->vb_ml.ml_leaf)->nextproc) (tvbp->vb_ml.ml_last_match, tvbp->vb_ml.ml_remaining_objid.num_components, tvbp->vb_ml.ml_remaining_objid.component_list, pktp, tvbp); tvbp->vb_flags |= VFLAG_NEXT_STARTED; } return(1); }return(0);}/****************************************************************************NAME: envoy_ax_sa_bulk_redoPURPOSE: Continuation of bulk processing. This routine is responsible for determining if we should do another repitition and finding the objects and calling the routines if so. If we think processing is finished we set the phase word to be next_done.PARAMETERS: SNMP_PKT_T * the partially processed packetRETURNS: void****************************************************************************/static void envoy_ax_sa_bulk_redo(SNMP_PKT_T *pktp){VBL_T *vblp;VB_T *vbp, *tvbp, *newvbp;int count, indx, nonreps, restart_flag = 0;/* Determine if we want to try another round of nexts */if (pktp->pdu.std_pdu.max_reps <= 1){ pktp->phase = VFLAG_NEXT_DONE; return; }/* Find the correct vblist to work with. Bulks may have several vblists chained togther, we want the last one (the only one that may have ops outstanding). The other pdus only have one vblist */for(vblp = &(pktp->pdu.std_pdu.std_vbl); vblp->vblp; vblp = vblp->vblp) ;if (((vbp = vblp->vblist) == 0) || ((count = vblp->vbl_count) == 0)) { pktp->phase = VFLAG_NEXT_DONE; return; }if (vblp == &(pktp->pdu.std_pdu.std_vbl)) nonreps = pktp->pdu.std_pdu.non_reps;else nonreps = 0;/* if we ever decide to add a size check to limit the size of a repsone packet we would put the size check code here */for(indx = count - nonreps, tvbp = vbp + nonreps; indx; indx--, tvbp++) if (tvbp->vb_data_flags_n_type != VT_ENDOFMIB) break;if (indx == 0){ pktp->phase = VFLAG_NEXT_DONE; return; }/* So we want to try another round, start by decrementing the reps number then set up the next vblist in the chain */pktp->pdu.std_pdu.max_reps--; if ((vblp->vblp = VBList_Allocate(count - nonreps)) == 0) { pktp->pdu.std_pdu.error_status = GEN_ERR; pktp->phase = VFLAG_NEXT_DONE; return; }/* Attempt to find the correct object for each of the repeaters. Currently we copy all of the objs and then start any required nexts. Eventually we should copy objects tagged as ENDOFMIB (we aren't going to find anything new) and tabular objects. We will run find_next_object on scalar objects as there won't be anymore instances. */for(indx = count - nonreps, tvbp = vbp + nonreps, newvbp = vblp->vblp->vblist; indx; indx--, tvbp++, newvbp++) { if (clone_object_id((&tvbp->vb_obj_id), (&newvbp->vb_obj_id))) { /* We were unable to clone an object so we return a gen err */ pktp->pdu.std_pdu.error_status = GEN_ERR; pktp->phase = VFLAG_NEXT_DONE; return; } if (tvbp->vb_data_flags_n_type == VT_ENDOFMIB) { newvbp->vb_data_flags_n_type = VT_ENDOFMIB; newvbp->vb_flags |= VFLAG_NEXT_STARTED | VFLAG_NEXT_DONE; } else { restart_flag = 1; /* And copy the mib leaf information */ newvbp->vb_ml.ml_node = tvbp->vb_ml.ml_node; newvbp->vb_ml.ml_flags = ML_IS_LEAF; newvbp->vb_ml.ml_last_match = tvbp->vb_ml.ml_last_match; newvbp->vb_ml.ml_remaining_objid.num_components = tvbp->vb_ml.ml_remaining_objid.num_components; newvbp->vb_ml.ml_remaining_objid.component_list = newvbp->vb_obj_id.component_list + newvbp->vb_obj_id.num_components - newvbp->vb_ml.ml_remaining_objid.num_components; } }if (restart_flag) { for(indx = count - nonreps, newvbp = vblp->vblp->vblist; indx; indx--, newvbp++) { /* If the next started flag is set then either we set it above or the nextproc of some other var bind has claimed responsibility for this var bind. In either case we skip this var bind and continue */ if (newvbp->vb_flags & (VFLAG_NEXT_STARTED | VFLAG_NEXT_DONE)) continue; ((newvbp->vb_ml.ml_leaf)->nextproc) (newvbp->vb_ml.ml_last_match, newvbp->vb_ml.ml_remaining_objid.num_components, newvbp->vb_ml.ml_remaining_objid.component_list, pktp, newvbp); newvbp->vb_flags |= VFLAG_NEXT_STARTED; } return; }else { pktp->phase = VFLAG_NEXT_DONE; return; }}/****************************************************************************NAME: envoy_ax_sa_next_continuePURPOSE: Determine if all the gets or nexts associated with the packet have finished. If they haven't we release the continue lock and return. If they have we check and see if we need to run try another round of nexts, either because we couldn't find an instance or we are processing a bulk and need to try the entire set again.PARAMETERS: SNMP_PKT_T * the partially processed next/bulk pduRETURNS: void****************************************************************************/static void envoy_ax_sa_next_continue(SNMP_PKT_T *pktp){VBL_T *vblp;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) *//* We do most of our processing in a while loop to catch redos or new reps that finish immediately and aren't using the callback scheme. We start by finding the correct vblist to work with. For nexts there will be only one but bulks may have several chained together, in this case we want the last one which is the only one that may have ops outstanding. If some of the vbs haven't completed we release the lock and bail out, otherwise we bail out if we have an error, finally we figure out if we have more work to do, either in the current rep or (if bulk) in the next rep. */ while(1) { if (pktp->phase == VFLAG_NEXT_DONE) break; for(vblp = &(pktp->pdu.std_pdu.std_vbl); vblp->vblp; vblp = vblp->vblp) ; vbp = vblp->vblist; count = vblp->vbl_count; for(; count; count--, vbp++) { if (!(vbp->vb_flags & VFLAG_NEXT_DONE)) {#if (INSTALL_ENVOY_CONTINUE_REENTRANT) ENVOY_SNMP_RELEASE_WRITE_LOCK(pktp->continue_lock);#endif return; } } if (pktp->pdu.std_pdu.error_status) break; /* Process the next set of the current rep, 0 indicates that we try any next reps anything else indicates we shouldn't, the packet phase word will be used to indicate if we are done (perhaps due to an error). If necessary we process the next rep, a return of 0 indicates that we are done. */ if (envoy_ax_sa_next_redo(pktp)) continue; envoy_ax_sa_bulk_redo(pktp); } /* while(1) */#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_nextpduPURPOSE: Start processing of a next or bulk packet. Primarily we will be finding the next objects and starting the next method routine associated with them. However there are some complications. For objects that have the include bit set we need to try and find the object and run its get routine. If the object or instance don't exist we drop into the next processing.PARAMETERS: SNMP_PKT_T * the decoded NEXT/BULK pduRETURNS: void****************************************************************************/void envoy_ax_sa_next_pdu(SNMP_PKT_T *pktp){VB_T *vbp, *ovbp, *oldvbp, *newvbp;INT_32_T maxreps, *err_stat;int nonreps, count, indx, include_flag = 0;/* 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_next_continue;/* get some initial information */if (((oldvbp = pktp->pdu.std_pdu.std_vbl.vblist) == 0) || ((count = pktp->pdu.std_pdu.std_vbl.vbl_count) == 0)) { pktp->phase = VFLAG_NEXT_DONE; envoy_ax_sa_next_continue(pktp); return; }/* If this is a bulk request pull the maxreps and nonreps info from the packet and rationalize it. */if (pktp->pdu_type == GET_BULK_REQUEST_PDU) { maxreps = pktp->pdu.std_pdu.max_reps; nonreps = pktp->pdu.std_pdu.non_reps; if (nonreps > count) { nonreps = count; maxreps = 1; } if (maxreps < 1) { maxreps = 1; /* This is kinda wierd, the manager sent a bulk packet but doesn't want any of the repeaters, adjust the counters */ if (nonreps == 0) { Clean_vb_list(&pktp->pdu.std_pdu.std_vbl); pktp->pdu.std_pdu.std_vbl.vblist = 0; pktp->pdu.std_pdu.std_vbl.vbl_count = 0; return; } count = nonreps; } /* Stash the fixed up information back into the packet */ pktp->pdu.std_pdu.max_reps = maxreps; pktp->pdu.std_pdu.non_reps = nonreps; }else { /* set the default values for a next request */ pktp->pdu.std_pdu.max_reps = 1; pktp->pdu.std_pdu.non_reps = 0; }/* Some errors may require us to use the original list so we save the original and allocate space for a new one. The objid for the new vbs will be filled in by the find_next_object routine, but we will need to clone the object id if find_next_object tells us their aren't any more objects. */if ((newvbp = VarBindList_Allocate(count)) == 0) { *err_stat = GEN_ERR; envoy_ax_sa_next_continue(pktp); return; }pktp->pdu.std_pdu.saved_vbl.vbl_count = pktp->pdu.std_pdu.std_vbl.vbl_count;pktp->pdu.std_pdu.saved_vbl.vblist = oldvbp;pktp->pdu.std_pdu.std_vbl.vbl_count = count;pktp->pdu.std_pdu.std_vbl.vblist = newvbp;/* If any of the requested objects have the include bit turned on we need to try a get first. First we step through the list tagging all the non-include objects as done this will prevent any method routines from trying to process them as gets. We tag them so we can reset the done bits after calling the gets and process them using nexts. We use a no such instance exception as the tag as any get methods that can't find an instance will use that and they need to be re-processed as well. In the same loop we try to find objects for the included var binds, any that don't have objects are tagged, again using no such instance. Finally we call the gets. Then retag the list and process it for nexts. We need to clone the object ids as we are using a new copy of the varbind list, if we can't clone an object return a gen err. */for(indx = count, ovbp = oldvbp, vbp = newvbp; indx; indx--, ovbp++, vbp++) { if (ovbp->ax_flags) { if (clone_object_id(&ovbp->vb_obj_id, &vbp->vb_obj_id)) { *err_stat = GEN_ERR; pktp->phase = VFLAG_NEXT_DONE; envoy_ax_sa_next_continue(pktp); return; } 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_NOSUCHINS; vbp->vb_flags |= VFLAG_GET_STARTED | VFLAG_GET_DONE; } /* if ((find_object...) */ else include_flag = 1; } else { vbp->vb_data_flags_n_type = VT_NOSUCHINS; vbp->vb_flags |= VFLAG_GET_STARTED | VFLAG_GET_DONE; } }/* If we have any include objects we loop through the vblist again and start some 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. Loop through the list resetting any objects that are tagged as no such instance. This will cover the objects we tagged and any objects for which the get routine failed to find an instance. */if (include_flag) { for(indx = count, vbp = newvbp; indx; indx--, vbp++) { if (vbp->vb_flags & (VFLAG_GET_STARTED | VFLAG_GET_DONE)) continue;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -