table_array.c

00001 /*
00002  * table_array.c
00003  * $Id: table_array.c 14356 2006-03-08 22:48:18Z rstory $
00004  */
00005 
00006 #include <net-snmp/net-snmp-config.h>
00007 
00008 #if HAVE_STRING_H
00009 #include <string.h>
00010 #else
00011 #include <strings.h>
00012 #endif
00013 
00014 #include <net-snmp/net-snmp-includes.h>
00015 #include <net-snmp/agent/net-snmp-agent-includes.h>
00016 
00017 #include <net-snmp/agent/table.h>
00018 #include <net-snmp/agent/table_array.h>
00019 #include <net-snmp/library/container.h>
00020 #include <net-snmp/library/snmp_assert.h>
00021 
00022 /*
00023  * snmp.h:#define SNMP_MSG_INTERNAL_SET_BEGIN        -1 
00024  * snmp.h:#define SNMP_MSG_INTERNAL_SET_RESERVE1     0 
00025  * snmp.h:#define SNMP_MSG_INTERNAL_SET_RESERVE2     1 
00026  * snmp.h:#define SNMP_MSG_INTERNAL_SET_ACTION       2 
00027  * snmp.h:#define SNMP_MSG_INTERNAL_SET_COMMIT       3 
00028  * snmp.h:#define SNMP_MSG_INTERNAL_SET_FREE         4 
00029  * snmp.h:#define SNMP_MSG_INTERNAL_SET_UNDO         5 
00030  */
00031 
00032 static const char *mode_name[] = {
00033     "Reserve 1",
00034     "Reserve 2",
00035     "Action",
00036     "Commit",
00037     "Free",
00038     "Undo"
00039 };
00040 
00041 /*
00042  * PRIVATE structure for holding important info for each table.
00043  */
00044 typedef struct table_container_data_s {
00045 
00047     netsnmp_table_registration_info *tblreg_info;
00048 
00050    netsnmp_container          *table;
00051 
00052     /*
00053      * mutex_type                lock;
00054      */
00055 
00058     int             group_rows;
00059 
00061     netsnmp_table_array_callbacks *cb;
00062 
00063 } table_container_data;
00064 
00134 /**********************************************************************
00135  **********************************************************************
00136  *                                                                    *
00137  *                                                                    *
00138  * PUBLIC Registration functions                                      *
00139  *                                                                    *
00140  *                                                                    *
00141  **********************************************************************
00142  **********************************************************************/
00148 int
00149 netsnmp_table_container_register(netsnmp_handler_registration *reginfo,
00150                              netsnmp_table_registration_info *tabreg,
00151                              netsnmp_table_array_callbacks *cb,
00152                              netsnmp_container *container,
00153                              int group_rows)
00154 {
00155     table_container_data *tad = SNMP_MALLOC_TYPEDEF(table_container_data);
00156     if (!tad)
00157         return SNMPERR_GENERR;
00158     tad->tblreg_info = tabreg;  /* we need it too, but it really is not ours */
00159 
00160     if (!cb) {
00161         snmp_log(LOG_ERR, "table_array registration with no callbacks\n" );
00162         free(tad); /* SNMP_FREE is overkill for local var */
00163         return SNMPERR_GENERR;
00164     }
00165     /*
00166      * check for required callbacks
00167      */
00168     if ((cb->can_set &&
00169          ((NULL==cb->duplicate_row) || (NULL==cb->delete_row) ||
00170           (NULL==cb->row_copy)) )) {
00171         snmp_log(LOG_ERR, "table_array registration with incomplete "
00172                  "callback structure.\n");
00173         free(tad); /* SNMP_FREE is overkill for local var */
00174         return SNMPERR_GENERR;
00175     }
00176 
00177     if (NULL==container) {
00178         tad->table = netsnmp_container_find("table_array");
00179         snmp_log(LOG_ERR, "table_array couldn't allocate container\n" );
00180         free(tad); /* SNMP_FREE is overkill for local var */
00181         return SNMPERR_GENERR;
00182     } else
00183         tad->table = container;
00184     if (NULL==tad->table->compare)
00185         tad->table->compare = netsnmp_compare_netsnmp_index;
00186     if (NULL==tad->table->ncompare)
00187         tad->table->ncompare = netsnmp_ncompare_netsnmp_index;
00188     
00189     tad->cb = cb;
00190 
00191     reginfo->handler->myvoid = tad;
00192 
00193     return netsnmp_register_table(reginfo, tabreg);
00194 }
00195 
00196 int
00197 netsnmp_table_array_register(netsnmp_handler_registration *reginfo,
00198                              netsnmp_table_registration_info *tabreg,
00199                              netsnmp_table_array_callbacks *cb,
00200                              netsnmp_container *container,
00201                              int group_rows)
00202 {
00203     netsnmp_inject_handler(reginfo,
00204                            netsnmp_create_handler(reginfo->handlerName,
00205                                netsnmp_table_array_helper_handler));
00206     return netsnmp_table_container_register(reginfo, tabreg, cb,
00207                                             container, group_rows);
00208 }
00209 
00211 netsnmp_mib_handler *
00212 netsnmp_find_table_array_handler(netsnmp_handler_registration *reginfo)
00213 {
00214     netsnmp_mib_handler *mh;
00215     if (!reginfo)
00216         return NULL;
00217     mh = reginfo->handler;
00218     while (mh) {
00219         if (mh->access_method == netsnmp_table_array_helper_handler)
00220             break;
00221         mh = mh->next;
00222     }
00223 
00224     return mh;
00225 }
00226 
00228 netsnmp_container      *
00229 netsnmp_extract_array_context(netsnmp_request_info *request)
00230 {
00231     return netsnmp_request_get_list_data(request, TABLE_ARRAY_NAME);
00232 }
00233 
00235 int
00236 netsnmp_table_array_check_row_status(netsnmp_table_array_callbacks *cb,
00237                                      netsnmp_request_group *ag,
00238                                      long *rs_new, long *rs_old)
00239 {
00240     netsnmp_index *row_ctx;
00241     netsnmp_index *undo_ctx;
00242     if (!ag || !cb)
00243         return SNMPERR_GENERR;
00244     row_ctx  = ag->existing_row;
00245     undo_ctx = ag->undo_info;
00246     
00247     /*
00248      * xxx-rks: revisit row delete scenario
00249      */
00250     if (row_ctx) {
00251         /*
00252          * either a new row, or change to old row
00253          */
00254         /*
00255          * is it set to active?
00256          */
00257         if (RS_IS_GOING_ACTIVE(*rs_new)) {
00258             /*
00259              * is it ready to be active?
00260              */
00261             if ((NULL==cb->can_activate) ||
00262                 cb->can_activate(undo_ctx, row_ctx, ag))
00263                 *rs_new = RS_ACTIVE;
00264             else
00265                 return SNMP_ERR_INCONSISTENTVALUE;
00266         } else {
00267             /*
00268              * not going active
00269              */
00270             if (undo_ctx) {
00271                 /*
00272                  * change
00273                  */
00274                 if (RS_IS_ACTIVE(*rs_old)) {
00275                     /*
00276                      * check pre-reqs for deactivation
00277                      */
00278                     if (cb->can_deactivate &&
00279                         !cb->can_deactivate(undo_ctx, row_ctx, ag)) {
00280                         return SNMP_ERR_INCONSISTENTVALUE;
00281                     }
00282                 }
00283             } else {
00284                 /*
00285                  * new row
00286                  */
00287             }
00288 
00289             if (*rs_new != RS_DESTROY) {
00290                 if ((NULL==cb->can_activate) ||
00291                     cb->can_activate(undo_ctx, row_ctx, ag))
00292                     *rs_new = RS_NOTINSERVICE;
00293                 else
00294                     *rs_new = RS_NOTREADY;
00295             } else {
00296                 if (cb->can_delete && !cb->can_delete(undo_ctx, row_ctx, ag)) {
00297                     return SNMP_ERR_INCONSISTENTVALUE;
00298                 }
00299                 ag->row_deleted = 1;
00300             }
00301         }
00302     } else {
00303         /*
00304          * check pre-reqs for delete row
00305          */
00306         if (cb->can_delete && !cb->can_delete(undo_ctx, row_ctx, ag)) {
00307             return SNMP_ERR_INCONSISTENTVALUE;
00308         }
00309     }
00310 
00311     return SNMP_ERR_NOERROR;
00312 }
00313 
00317 /**********************************************************************
00318  **********************************************************************
00319  **********************************************************************
00320  **********************************************************************
00321  *                                                                    *
00322  *                                                                    *
00323  *                                                                    *
00324  *                                                                    *
00325  * EVERYTHING BELOW THIS IS PRIVATE IMPLEMENTATION DETAILS.           *
00326  *                                                                    *
00327  *                                                                    *
00328  *                                                                    *
00329  *                                                                    *
00330  **********************************************************************
00331  **********************************************************************
00332  **********************************************************************
00333  **********************************************************************/
00334 
00335 /**********************************************************************
00336  **********************************************************************
00337  *                                                                    *
00338  *                                                                    *
00339  * Structures, Utility/convenience functions                          *
00340  *                                                                    *
00341  *                                                                    *
00342  **********************************************************************
00343  **********************************************************************/
00344 /*
00345  * context info for SET requests
00346  */
00347 typedef struct set_context_s {
00348     netsnmp_agent_request_info *agtreq_info;
00349     table_container_data *tad;
00350     int             status;
00351 } set_context;
00352 
00353 static void
00354 release_netsnmp_request_group(netsnmp_index *g, void *v)
00355 {
00356     netsnmp_request_group_item *tmp;
00357     netsnmp_request_group *group = (netsnmp_request_group *) g;
00358 
00359     if (!g)
00360         return;
00361     while (group->list) {
00362         tmp = group->list;
00363         group->list = tmp->next;
00364         free(tmp);
00365     }
00366 
00367     free(group);
00368 }
00369 
00370 static void
00371 release_netsnmp_request_groups(void *vp)
00372 {
00373     netsnmp_container *c = (netsnmp_container*)vp;
00374     CONTAINER_FOR_EACH(c, (netsnmp_container_obj_func*)
00375                        release_netsnmp_request_group, NULL);
00376     CONTAINER_FREE(c);
00377 }
00378 
00379 void
00380 build_new_oid(netsnmp_handler_registration *reginfo,
00381               netsnmp_table_request_info *tblreq_info,
00382               netsnmp_index *row, netsnmp_request_info *current)
00383 {
00384     oid             coloid[MAX_OID_LEN];
00385     int             coloid_len;
00386 
00387     if (!tblreq_info || !reginfo || !row || !current)
00388         return;
00389 
00390     coloid_len = reginfo->rootoid_len + 2;
00391     memcpy(coloid, reginfo->rootoid, reginfo->rootoid_len * sizeof(oid));
00392 
00394     coloid[reginfo->rootoid_len] = 1;
00395 
00397     coloid[reginfo->rootoid_len + 1] = tblreq_info->colnum;
00398 
00400     memcpy(&coloid[reginfo->rootoid_len + 2], row->oids,
00401            row->len * sizeof(oid));
00402 
00403     snmp_set_var_objid(current->requestvb, coloid,
00404                        reginfo->rootoid_len + 2 + row->len);
00405 }
00406 
00407 /**********************************************************************
00408  **********************************************************************
00409  *                                                                    *
00410  *                                                                    *
00411  * GET procession functions                                           *
00412  *                                                                    *
00413  *                                                                    *
00414  **********************************************************************
00415  **********************************************************************/
00416 int
00417 process_get_requests(netsnmp_handler_registration *reginfo,
00418                      netsnmp_agent_request_info *agtreq_info,
00419                      netsnmp_request_info *requests,
00420                      table_container_data * tad)
00421 {
00422     int             rc = SNMP_ERR_NOERROR;
00423     netsnmp_request_info *current;
00424     netsnmp_index *row = NULL;
00425     netsnmp_table_request_info *tblreq_info;
00426     netsnmp_variable_list *var;
00427 
00428     /*
00429      * Loop through each of the requests, and
00430      * try to find the appropriate row from the container.
00431      */
00432     for (current = requests; current; current = current->next) {
00433 
00434         var = current->requestvb;
00435         DEBUGMSGTL(("table_array:get",
00436                     "  process_get_request oid:"));
00437         DEBUGMSGOID(("table_array:get", var->name,
00438                      var->name_length));
00439         DEBUGMSG(("table_array:get", "\n"));
00440 
00441         /*
00442          * skip anything that doesn't need processing.
00443          */
00444         if (current->processed != 0) {
00445             DEBUGMSGTL(("table_array:get", "already processed\n"));
00446             continue;
00447         }
00448 
00449         /*
00450          * Get pointer to the table information for this request. This
00451          * information was saved by table_helper_handler. When
00452          * debugging, we double check a few assumptions. For example,
00453          * the table_helper_handler should enforce column boundaries.
00454          */
00455         tblreq_info = netsnmp_extract_table_info(current);
00456         netsnmp_assert(tblreq_info->colnum <= tad->tblreg_info->max_column);
00457 
00458         if ((agtreq_info->mode == MODE_GETNEXT) ||
00459             (agtreq_info->mode == MODE_GETBULK)) {
00460             /*
00461              * find the row
00462              */
00463             row = netsnmp_table_index_find_next_row(tad->table, tblreq_info);
00464             if (!row) {
00465                 /*
00466                  * no results found.
00467                  *
00468                  * xxx-rks: how do we skip this entry for the next handler,
00469                  * but still allow it a chance to hit another handler?
00470                  */
00471                 DEBUGMSGTL(("table_array:get", "no row found\n"));
00472                 netsnmp_set_request_error(agtreq_info, current,
00473                                           SNMP_ENDOFMIBVIEW);
00474                 continue;
00475             }
00476 
00477             /*
00478              * * if data was found, make sure it has the column we want
00479              */
00480 /* xxx-rks: add suport for sparse tables */
00481 
00482             /*
00483              * build new oid
00484              */
00485             build_new_oid(reginfo, tblreq_info, row, current);
00486 
00487         } 
00488         else {
00489             netsnmp_index index;
00490             index.oids = tblreq_info->index_oid;
00491             index.len = tblreq_info->index_oid_len;
00492 
00493             row = CONTAINER_FIND(tad->table, &index);
00494             if (!row) {
00495                 DEBUGMSGTL(("table_array:get", "no row found\n"));
00496                 netsnmp_set_request_error(agtreq_info, current,
00497                                           SNMP_NOSUCHINSTANCE);
00498                 continue;
00499             }
00500         } 
00502         /*
00503          * get the data
00504          */
00505         rc = tad->cb->get_value(current, row, tblreq_info);
00506 
00507     } 
00509     return rc;
00510 }
00511 
00512 /**********************************************************************
00513  **********************************************************************
00514  *                                                                    *
00515  *                                                                    *
00516  * SET procession functions                                           *
00517  *                                                                    *
00518  *                                                                    *
00519  **********************************************************************
00520  **********************************************************************/
00521 
00522 void
00523 group_requests(netsnmp_agent_request_info *agtreq_info,
00524                netsnmp_request_info *requests,
00525                netsnmp_container *request_group, table_container_data * tad)
00526 {
00527     netsnmp_table_request_info *tblreq_info;
00528     netsnmp_variable_list *var;
00529     netsnmp_index *row, *tmp, index;
00530     netsnmp_request_info *current;
00531     netsnmp_request_group *g;
00532     netsnmp_request_group_item *i;
00533 
00534     for (current = requests; current; current = current->next) {
00535 
00536         var = current->requestvb;
00537 
00538         /*
00539          * skip anything that doesn't need processing.
00540          */
00541         if (current->processed != 0) {
00542             DEBUGMSGTL(("table_array:group",
00543                         "already processed\n"));
00544             continue;
00545         }
00546 
00547         /*
00548          * 3.2.1 Setup and paranoia
00549          * *
00550          * * Get pointer to the table information for this request. This
00551          * * information was saved by table_helper_handler. When
00552          * * debugging, we double check a few assumptions. For example,
00553          * * the table_helper_handler should enforce column boundaries.
00554          */
00555         row = NULL;
00556         tblreq_info = netsnmp_extract_table_info(current);
00557         netsnmp_assert(tblreq_info->colnum <= tad->tblreg_info->max_column);
00558 
00559         /*
00560          * search for index
00561          */
00562         index.oids = tblreq_info->index_oid;
00563         index.len = tblreq_info->index_oid_len;
00564         tmp = CONTAINER_FIND(request_group, &index);
00565         if (tmp) {
00566             DEBUGMSGTL(("table_array:group",
00567                         "    existing group:"));
00568             DEBUGMSGOID(("table_array:group", index.oids,
00569                          index.len));
00570             DEBUGMSG(("table_array:group", "\n"));
00571             g = (netsnmp_request_group *) tmp;
00572             i = SNMP_MALLOC_TYPEDEF(netsnmp_request_group_item);
00573             i->ri = current;
00574             i->tri = tblreq_info;
00575             i->next = g->list;
00576             g->list = i;
00577 
00579             continue;
00580         }
00581 
00582         DEBUGMSGTL(("table_array:group", "    new group"));
00583         DEBUGMSGOID(("table_array:group", index.oids,
00584                      index.len));
00585         DEBUGMSG(("table_array:group", "\n"));
00586         g = SNMP_MALLOC_TYPEDEF(netsnmp_request_group);
00587         i = SNMP_MALLOC_TYPEDEF(netsnmp_request_group_item);
00588         g->list = i;
00589         g->table = tad->table;
00590         i->ri = current;
00591         i->tri = tblreq_info;
00594         /*
00595          * search for row. all changes are made to the original row,
00596          * later, we'll make a copy in undo_info before we start processing.
00597          */
00598         row = g->existing_row = CONTAINER_FIND(tad->table, &index);
00599         if (!g->existing_row) {
00600             if (!tad->cb->create_row) {
00601                 if(MODE_IS_SET(agtreq_info->mode))
00602                     netsnmp_set_request_error(agtreq_info, current,
00603                                               SNMP_ERR_NOTWRITABLE);
00604                 else
00605                     netsnmp_set_request_error(agtreq_info, current,
00606                                               SNMP_NOSUCHINSTANCE);
00607                 free(g);
00608                 free(i);
00609                 continue;
00610             }
00612             row = g->existing_row = tad->cb->create_row(&index);
00613             if (!row) {
00614                 /* xxx-rks : parameter to create_row to allow
00615                  * for better error reporting. */
00616                 netsnmp_set_request_error(agtreq_info, current,
00617                                           SNMP_ERR_GENERR);
00618                 free(g);
00619                 free(i);
00620                 continue;
00621             }
00622             g->row_created = 1;
00623         }
00624 
00625         g->index.oids = row->oids;
00626         g->index.len = row->len;
00627 
00628         CONTAINER_INSERT(request_group, g);
00629 
00630     } 
00631 }
00632 
00633 static void
00634 process_set_group(netsnmp_index *o, void *c)
00635 {
00636     /* xxx-rks: should we continue processing after an error?? */
00637     set_context           *context = (set_context *) c;
00638     netsnmp_request_group *ag = (netsnmp_request_group *) o;
00639     int                    rc = SNMP_ERR_NOERROR;
00640 
00641     switch (context->agtreq_info->mode) {
00642 
00643     case MODE_SET_RESERVE1:
00645         /*
00646          * if not a new row, save undo info
00647          */
00648         if (ag->row_created == 0) {
00649             if (context->tad->cb->duplicate_row)
00650                 ag->undo_info = context->tad->cb->duplicate_row(ag->existing_row);
00651             else
00652                 ag->undo_info = NULL;
00653             if (NULL == ag->undo_info) {
00654                 rc = SNMP_ERR_RESOURCEUNAVAILABLE;
00655                 break;
00656             }
00657         }
00658         
00659         if (context->tad->cb->set_reserve1)
00660             context->tad->cb->set_reserve1(ag);
00661         break;
00662 
00663     case MODE_SET_RESERVE2:
00664         if (context->tad->cb->set_reserve2)
00665             context->tad->cb->set_reserve2(ag);
00666         break;
00667 
00668     case MODE_SET_ACTION:
00669         if (context->tad->cb->set_action)
00670             context->tad->cb->set_action(ag);
00671         break;
00672 
00673     case MODE_SET_COMMIT:
00674         if (ag->row_created == 0) {
00675             /*
00676              * this is an existing row, has it been deleted?
00677              */
00678             if (ag->row_deleted == 1) {
00679                 DEBUGMSGT((TABLE_ARRAY_NAME, "action: deleting row\n"));
00680                 if (CONTAINER_REMOVE(ag->table, ag->existing_row) != 0) {
00681                     rc = SNMP_ERR_COMMITFAILED;
00682                     break;
00683                 }
00684             }
00685         } else if (ag->row_deleted == 0) {
00686             /*
00687              * new row (that hasn't been deleted) should be inserted
00688              */
00689             DEBUGMSGT((TABLE_ARRAY_NAME, "action: inserting row\n"));
00690             if (CONTAINER_INSERT(ag->table, ag->existing_row) != 0) {
00691                 rc = SNMP_ERR_COMMITFAILED;
00692                 break;
00693             }
00694         }
00695 
00696         if (context->tad->cb->set_commit)
00697             context->tad->cb->set_commit(ag);
00698 
00700         if (ag->undo_info) {
00701             context->tad->cb->delete_row(ag->undo_info);
00702             ag->undo_info = NULL;
00703         }
00704 
00705 #if 0
00706         /* XXX-rks: finish row cooperative notifications
00707          * if the table has requested it, send cooperative notifications
00708          * for row operations.
00709          */
00710         if (context->tad->notifications) {
00711             if (ag->undo_info) {
00712                 if (!ag->existing_row)
00713                     netsnmp_monitor_notify(EVENT_ROW_DEL);
00714                 else
00715                     netsnmp_monitor_notify(EVENT_ROW_MOD);
00716             }
00717             else
00718                 netsnmp_monitor_notify(EVENT_ROW_ADD);
00719         }
00720 #endif
00721 
00722         if ((ag->row_created == 0) && (ag->row_deleted == 1)) {
00723             context->tad->cb->delete_row(ag->existing_row);
00724             ag->existing_row = NULL;
00725         }
00726         break;
00727 
00728     case MODE_SET_FREE:
00729         if (context->tad->cb->set_free)
00730             context->tad->cb->set_free(ag);
00731 
00733         if (ag->row_created == 1) {
00734             if (context->tad->cb->delete_row)
00735                 context->tad->cb->delete_row(ag->existing_row);
00736             ag->existing_row = NULL;
00737         }
00738         else {
00739             if (context->tad->cb->delete_row)
00740                 context->tad->cb->delete_row(ag->undo_info);
00741             ag->undo_info = NULL;
00742         }
00743         break;
00744 
00745     case MODE_SET_UNDO:
00746         /*
00747          * status already set - don't change it now
00748          */
00749         if (context->tad->cb->set_undo)
00750             context->tad->cb->set_undo(ag);
00751 
00752         /*
00753          * no more use for undo_info, so free it
00754          */
00755         if (ag->row_created == 0) {
00756             /*
00757              * restore old values
00758              */
00759             context->tad->cb->row_copy(ag->existing_row, ag->undo_info);
00760             context->tad->cb->delete_row(ag->undo_info);
00761             ag->undo_info = NULL;
00762         }
00763         else {
00764             context->tad->cb->delete_row(ag->existing_row);
00765             ag->existing_row = NULL;
00766         }
00767         break;
00768 
00769     default:
00770         snmp_log(LOG_ERR, "unknown mode processing SET for "
00771                  "netsnmp_table_array_helper_handler\n");
00772         rc = SNMP_ERR_GENERR;
00773         break;
00774     }
00775     
00776     if (rc)
00777         netsnmp_set_request_error(context->agtreq_info,
00778                                   ag->list->ri, rc);
00779                                                
00780 }
00781 
00782 int
00783 process_set_requests(netsnmp_agent_request_info *agtreq_info,
00784                      netsnmp_request_info *requests,
00785                      table_container_data * tad, char *handler_name)
00786 {
00787     set_context         context;
00788     netsnmp_container  *request_group;
00789 
00790     /*
00791      * create and save structure for set info
00792      */
00793     request_group = (netsnmp_container*) netsnmp_agent_get_list_data
00794         (agtreq_info, handler_name);
00795     if (request_group == NULL) {
00796         netsnmp_data_list *tmp;
00797         request_group = netsnmp_container_find("request_group:"
00798                                                "table_container");
00799         request_group->compare = netsnmp_compare_netsnmp_index;
00800         request_group->ncompare = netsnmp_ncompare_netsnmp_index;
00801 
00802         DEBUGMSGTL(("table_array", "Grouping requests by oid\n"));
00803 
00804         tmp = netsnmp_create_data_list(handler_name,
00805                                        request_group,
00806                                        release_netsnmp_request_groups);
00807         netsnmp_agent_add_list_data(agtreq_info, tmp);
00808         /*
00809          * group requests.
00810          */
00811         group_requests(agtreq_info, requests, request_group, tad);
00812     }
00813 
00814     /*
00815      * process each group one at a time
00816      */
00817     context.agtreq_info = agtreq_info;
00818     context.tad = tad;
00819     context.status = SNMP_ERR_NOERROR;
00820     CONTAINER_FOR_EACH(request_group,
00821                        (netsnmp_container_obj_func*)process_set_group,
00822                        &context);
00823 
00824     return context.status;
00825 }
00826 
00827 
00828 /**********************************************************************
00829  **********************************************************************
00830  *                                                                    *
00831  *                                                                    *
00832  * netsnmp_table_array_helper_handler()                               *
00833  *                                                                    *
00834  *                                                                    *
00835  **********************************************************************
00836  **********************************************************************/
00837 int
00838 netsnmp_table_array_helper_handler(netsnmp_mib_handler *handler,
00839                                    netsnmp_handler_registration *reginfo,
00840                                    netsnmp_agent_request_info *agtreq_info,
00841                                    netsnmp_request_info *requests)
00842 {
00843 
00844     /*
00845      * First off, get our pointer from the handler. This
00846      * lets us get to the table registration information we
00847      * saved in get_table_array_handler(), as well as the
00848      * container where the actual table data is stored.
00849      */
00850     int             rc = SNMP_ERR_NOERROR;
00851     table_container_data *tad = (table_container_data *)handler->myvoid;
00852 
00853     if (agtreq_info->mode < 0 || agtreq_info->mode > 5) {
00854         DEBUGMSGTL(("table_array", "Mode %d, Got request:\n",
00855                     agtreq_info->mode));
00856     } else {
00857         DEBUGMSGTL(("table_array", "Mode %s, Got request:\n",
00858                     mode_name[agtreq_info->mode]));
00859     }
00860 
00861     if (MODE_IS_SET(agtreq_info->mode)) {
00862         /*
00863          * netsnmp_mutex_lock(&tad->lock);
00864          */
00865         rc = process_set_requests(agtreq_info, requests,
00866                                   tad, handler->handler_name);
00867         /*
00868          * netsnmp_mutex_unlock(&tad->lock);
00869          */
00870     } else
00871         rc = process_get_requests(reginfo, agtreq_info, requests, tad);
00872 
00873     if (rc != SNMP_ERR_NOERROR) {
00874         DEBUGMSGTL(("table_array", "processing returned rc %d\n", rc));
00875     }
00876     
00877     /*
00878      * Now we've done our processing. If there is another handler below us,
00879      * call them.
00880      */
00881     if (handler->next) {
00882         rc = netsnmp_call_next_handler(handler, reginfo, agtreq_info, requests);
00883         if (rc != SNMP_ERR_NOERROR) {
00884             DEBUGMSGTL(("table_array", "next handler returned rc %d\n", rc));
00885         }
00886     }
00887     
00888     return rc;
00889 }

net-snmpに対してSat Sep 5 13:14:27 2009に生成されました。  doxygen 1.4.7