table_data.c

00001 #include <net-snmp/net-snmp-config.h>
00002 
00003 #if HAVE_STRING_H
00004 #include <string.h>
00005 #else
00006 #include <strings.h>
00007 #endif
00008 
00009 #include <net-snmp/net-snmp-includes.h>
00010 #include <net-snmp/agent/net-snmp-agent-includes.h>
00011 
00012 #include <net-snmp/agent/table.h>
00013 #include <net-snmp/agent/table_data.h>
00014 #include <net-snmp/agent/read_only.h>
00015 
00035 /* ==================================
00036  *
00037  * Table Data API: Table maintenance
00038  *
00039  * ================================== */
00040 
00041 /*
00042  * generates the index portion of an table oid from a varlist.
00043  */
00044 void
00045 netsnmp_table_data_generate_index_oid(netsnmp_table_row *row)
00046 {
00047     build_oid(&row->index_oid, &row->index_oid_len, NULL, 0, row->indexes);
00048 }
00049 
00051 netsnmp_table_data *
00052 netsnmp_create_table_data(const char *name)
00053 {
00054     netsnmp_table_data *table = SNMP_MALLOC_TYPEDEF(netsnmp_table_data);
00055     if (name && table)
00056         table->name = strdup(name);
00057     return table;
00058 }
00059 
00061 netsnmp_table_row *
00062 netsnmp_create_table_data_row(void)
00063 {
00064     netsnmp_table_row *row = SNMP_MALLOC_TYPEDEF(netsnmp_table_row);
00065     return row;
00066 }
00067 
00069 netsnmp_table_row *
00070 netsnmp_table_data_clone_row(netsnmp_table_row *row)
00071 {
00072     netsnmp_table_row *newrow = NULL;
00073     if (!row)
00074         return NULL;
00075 
00076     memdup((u_char **) & newrow, (u_char *) row,
00077            sizeof(netsnmp_table_row));
00078     if (!newrow)
00079         return NULL;
00080 
00081     if (row->indexes) {
00082         newrow->indexes = snmp_clone_varbind(newrow->indexes);
00083         if (!newrow->indexes)
00084             return NULL;
00085     }
00086 
00087     if (row->index_oid) {
00088         memdup((u_char **) & newrow->index_oid,
00089                (u_char *) row->index_oid,
00090                row->index_oid_len * sizeof(oid));
00091         if (!newrow->index_oid)
00092             return NULL;
00093     }
00094 
00095     return newrow;
00096 }
00097 
00100 void           *
00101 netsnmp_table_data_delete_row(netsnmp_table_row *row)
00102 {
00103     void           *data;
00104 
00105     if (!row)
00106         return NULL;
00107 
00108     /*
00109      * free the memory we can 
00110      */
00111     if (row->indexes)
00112         snmp_free_varbind(row->indexes);
00113     SNMP_FREE(row->index_oid);
00114     data = row->data;
00115     free(row);
00116 
00117     /*
00118      * return the void * pointer 
00119      */
00120     return data;
00121 }
00122 
00129 int
00130 netsnmp_table_data_add_row(netsnmp_table_data *table,
00131                            netsnmp_table_row *row)
00132 {
00133     int rc, dup = 0;
00134     netsnmp_table_row *nextrow = NULL, *prevrow;
00135 
00136     if (!row || !table)
00137         return SNMPERR_GENERR;
00138 
00139     if (row->indexes)
00140         netsnmp_table_data_generate_index_oid(row);
00141 
00142     /*
00143      * we don't store the index info as it
00144      * takes up memory. 
00145      */
00146     if (!table->store_indexes) {
00147         snmp_free_varbind(row->indexes);
00148         row->indexes = NULL;
00149     }
00150 
00151     if (!row->index_oid) {
00152         snmp_log(LOG_ERR,
00153                  "illegal data attempted to be added to table %s (no index)\n",
00154                  table->name);
00155         return SNMPERR_GENERR;
00156     }
00157 
00158     /*
00159      * check for simple append
00160      */
00161     if ((prevrow = table->last_row) != NULL) {
00162         rc = snmp_oid_compare(prevrow->index_oid, prevrow->index_oid_len,
00163                               row->index_oid, row->index_oid_len);
00164         if (0 == rc)
00165             dup = 1;
00166     }
00167     else
00168         rc = 1;
00169     
00170     /*
00171      * if no last row, or newrow < last row, search the table and
00172      * insert it into the table in the proper oid-lexographical order 
00173      */
00174     if (rc > 0) {
00175         for (nextrow = table->first_row, prevrow = NULL;
00176              nextrow != NULL; prevrow = nextrow, nextrow = nextrow->next) {
00177             if (NULL == nextrow->index_oid) {
00178                 DEBUGMSGT(("table_data_add_data", "row doesn't have index!\n"));
00180                 continue;
00181             }
00182             rc = snmp_oid_compare(nextrow->index_oid, nextrow->index_oid_len,
00183                                   row->index_oid, row->index_oid_len);
00184             if(rc > 0)
00185                 break;
00186             if (0 == rc) {
00187                 dup = 1;
00188                 break;
00189             }
00190         }
00191     }
00192 
00193     if (dup) {
00194         /*
00195          * exact match.  Duplicate entries illegal 
00196          */
00197         snmp_log(LOG_WARNING,
00198                  "duplicate table data attempted to be entered. row exists\n");
00199         return SNMPERR_GENERR;
00200     }
00201 
00202     /*
00203      * ok, we have the location of where it should go 
00204      */
00205     /*
00206      * (after prevrow, and before nextrow) 
00207      */
00208     row->next = nextrow;
00209     row->prev = prevrow;
00210 
00211     if (row->next)
00212         row->next->prev = row;
00213 
00214     if (row->prev)
00215         row->prev->next = row;
00216 
00217     if (NULL == row->prev)      /* it's the (new) first row */
00218         table->first_row = row;
00219     if (NULL == row->next)      /* it's the last row */
00220         table->last_row = row;
00221 
00222     DEBUGMSGTL(("table_data_add_data", "added something...\n"));
00223 
00224     return SNMPERR_SUCCESS;
00225 }
00226 
00228 NETSNMP_INLINE void
00229 netsnmp_table_data_replace_row(netsnmp_table_data *table,
00230                                netsnmp_table_row *origrow,
00231                                netsnmp_table_row *newrow)
00232 {
00233     netsnmp_table_data_remove_row(table, origrow);
00234     netsnmp_table_data_add_row(table, newrow);
00235 }
00236 
00243 netsnmp_table_row *
00244 netsnmp_table_data_remove_row(netsnmp_table_data *table,
00245                               netsnmp_table_row *row)
00246 {
00247     if (!row || !table)
00248         return NULL;
00249 
00250     if (row->prev)
00251         row->prev->next = row->next;
00252     else
00253         table->first_row = row->next;
00254 
00255     if (row->next)
00256         row->next->prev = row->prev;
00257     else
00258         table->last_row = row->prev;
00259 
00260     return row;
00261 }
00262 
00269 void           *
00270 netsnmp_table_data_remove_and_delete_row(netsnmp_table_data *table,
00271                                          netsnmp_table_row *row)
00272 {
00273     if (!row || !table)
00274         return NULL;
00275 
00276     /*
00277      * remove it from the list 
00278      */
00279     netsnmp_table_data_remove_row(table, row);
00280     return netsnmp_table_data_delete_row(row);
00281 }
00282 
00283     /* =====================================
00284      * Generic API - mostly renamed wrappers
00285      * ===================================== */
00286 
00287 netsnmp_table_data *
00288 netsnmp_table_data_create_table(const char *name, long flags)
00289 {
00290     return netsnmp_create_table_data( name );
00291 }
00292 
00293 void
00294 netsnmp_table_data_delete_table( netsnmp_table_data *table )
00295 {
00296     netsnmp_table_row *row, *nextrow;
00297 
00298     if (!table)
00299         return;
00300 
00301     for (row = table->first_row; row; row=nextrow) {
00302         nextrow   = row->next;
00303         row->next = NULL;
00304         netsnmp_table_data_delete_row(row);
00305         /* Can't delete table-specific entry memory */
00306     }
00307     table->first_row = NULL;
00308 
00309     if (table->name) {
00310         SNMP_FREE(table->name);
00311         table->name = NULL;
00312     }
00313     SNMP_FREE(table);
00314     return;
00315 }
00316 
00317 netsnmp_table_row *
00318 netsnmp_table_data_create_row( void* entry )
00319 {
00320     netsnmp_table_row *row = SNMP_MALLOC_TYPEDEF(netsnmp_table_row);
00321     if (row)
00322         row->data = entry;
00323     return row;
00324 }
00325 
00326     /* netsnmp_table_data_clone_row() defined above */
00327 
00328 int
00329 netsnmp_table_data_copy_row( netsnmp_table_row  *old_row,
00330                              netsnmp_table_row  *new_row )
00331 {
00332     if (!old_row || !new_row)
00333         return -1;
00334 
00335     memcpy(new_row, old_row, sizeof(netsnmp_table_row));
00336 
00337     if (old_row->indexes)
00338         new_row->indexes = snmp_clone_varbind(old_row->indexes);
00339     if (old_row->index_oid)
00340         memdup((u_char **) & new_row->index_oid,
00341                (u_char *)    old_row->index_oid,
00342                old_row->index_oid_len * sizeof(oid));
00343     /* XXX - Doesn't copy table-specific row structure */
00344     return 0;
00345 }
00346 
00347     /*
00348      * netsnmp_table_data_delete_row()
00349      * netsnmp_table_data_add_row()
00350      * netsnmp_table_data_replace_row()
00351      * netsnmp_table_data_remove_row()
00352      *     all defined above
00353      */
00354 
00355 void *
00356 netsnmp_table_data_remove_delete_row(netsnmp_table_data *table,
00357                                      netsnmp_table_row *row)
00358 {
00359     return netsnmp_table_data_remove_and_delete_row(table, row);
00360 }
00361 
00362 
00363 /* ==================================
00364  *
00365  * Table Data API: MIB maintenance
00366  *
00367  * ================================== */
00368 
00370 netsnmp_mib_handler *
00371 netsnmp_get_table_data_handler(netsnmp_table_data *table)
00372 {
00373     netsnmp_mib_handler *ret = NULL;
00374 
00375     if (!table) {
00376         snmp_log(LOG_INFO,
00377                  "netsnmp_get_table_data_handler(NULL) called\n");
00378         return NULL;
00379     }
00380 
00381     ret =
00382         netsnmp_create_handler(TABLE_DATA_NAME,
00383                                netsnmp_table_data_helper_handler);
00384     if (ret) {
00385         ret->flags |= MIB_HANDLER_AUTO_NEXT;
00386         ret->myvoid = (void *) table;
00387     }
00388     return ret;
00389 }
00390 
00393 int
00394 netsnmp_register_table_data(netsnmp_handler_registration *reginfo,
00395                             netsnmp_table_data *table,
00396                             netsnmp_table_registration_info *table_info)
00397 {
00398     netsnmp_inject_handler(reginfo, netsnmp_get_table_data_handler(table));
00399     return netsnmp_register_table(reginfo, table_info);
00400 }
00401 
00404 int
00405 netsnmp_register_read_only_table_data(netsnmp_handler_registration *reginfo,
00406                                       netsnmp_table_data *table,
00407                                       netsnmp_table_registration_info *table_info)
00408 {
00409     netsnmp_inject_handler(reginfo, netsnmp_get_read_only_handler());
00410     return netsnmp_register_table_data(reginfo, table, table_info);
00411 }
00412 
00413 /*
00414  * The helper handler that takes care of passing a specific row of
00415  * data down to the lower handler(s).  It sets request->processed if
00416  * the request should not be handled.
00417  */
00418 int
00419 netsnmp_table_data_helper_handler(netsnmp_mib_handler *handler,
00420                                   netsnmp_handler_registration *reginfo,
00421                                   netsnmp_agent_request_info *reqinfo,
00422                                   netsnmp_request_info *requests)
00423 {
00424     netsnmp_table_data *table = (netsnmp_table_data *) handler->myvoid;
00425     netsnmp_request_info *request;
00426     int             valid_request = 0;
00427     netsnmp_table_row *row;
00428     netsnmp_table_request_info *table_info;
00429     netsnmp_table_registration_info *table_reg_info =
00430         netsnmp_find_table_registration_info(reginfo);
00431     int             result, regresult;
00432     int             oldmode;
00433 
00434     for (request = requests; request; request = request->next) {
00435         if (request->processed)
00436             continue;
00437 
00438         table_info = netsnmp_extract_table_info(request);
00439         if (!table_info)
00440             continue;           /* ack */
00441         switch (reqinfo->mode) {
00442         case MODE_GET:
00443         case MODE_GETNEXT:
00444         case MODE_SET_RESERVE1:
00445             netsnmp_request_add_list_data(request,
00446                                       netsnmp_create_data_list(
00447                                           TABLE_DATA_TABLE, table, NULL));
00448         }
00449 
00450         /*
00451          * find the row in question 
00452          */
00453         switch (reqinfo->mode) {
00454         case MODE_GETNEXT:
00455         case MODE_GETBULK:     /* XXXWWW */
00456             if (request->requestvb->type != ASN_NULL)
00457                 continue;
00458             /*
00459              * loop through data till we find the next row 
00460              */
00461             result = snmp_oid_compare(request->requestvb->name,
00462                                       request->requestvb->name_length,
00463                                       reginfo->rootoid,
00464                                       reginfo->rootoid_len);
00465             regresult = snmp_oid_compare(request->requestvb->name,
00466                                          SNMP_MIN(request->requestvb->
00467                                                   name_length,
00468                                                   reginfo->rootoid_len),
00469                                          reginfo->rootoid,
00470                                          reginfo->rootoid_len);
00471             if (regresult == 0
00472                 && request->requestvb->name_length < reginfo->rootoid_len)
00473                 regresult = -1;
00474 
00475             if (result < 0 || 0 == result) {
00476                 /*
00477                  * before us entirely, return the first 
00478                  */
00479                 row = table->first_row;
00480                 table_info->colnum = table_reg_info->min_column;
00481             } else if (regresult == 0 && request->requestvb->name_length ==
00482                        reginfo->rootoid_len + 1 &&
00483                        /* entry node must be 1, but any column is ok */
00484                        request->requestvb->name[reginfo->rootoid_len] == 1) {
00485                 /*
00486                  * exactly to the entry 
00487                  */
00488                 row = table->first_row;
00489                 table_info->colnum = table_reg_info->min_column;
00490             } else if (regresult == 0 && request->requestvb->name_length ==
00491                        reginfo->rootoid_len + 2 &&
00492                        /* entry node must be 1, but any column is ok */
00493                        request->requestvb->name[reginfo->rootoid_len] == 1) {
00494                 /*
00495                  * exactly to the column 
00496                  */
00497                 row = table->first_row;
00498             } else {
00499                 /*
00500                  * loop through all rows looking for the first one
00501                  * that is equal to the request or greater than it 
00502                  */
00503                 for (row = table->first_row; row; row = row->next) {
00504                     /*
00505                      * compare the index of the request to the row 
00506                      */
00507                     result =
00508                         snmp_oid_compare(row->index_oid,
00509                                          row->index_oid_len,
00510                                          request->requestvb->name + 2 +
00511                                          reginfo->rootoid_len,
00512                                          request->requestvb->name_length -
00513                                          2 - reginfo->rootoid_len);
00514                     if (result == 0) {
00515                         /*
00516                          * equal match, return the next row 
00517                          */
00518                         if (row) {
00519                             row = row->next;
00520                         }
00521                         break;
00522                     } else if (result > 0) {
00523                         /*
00524                          * the current row is greater than the
00525                          * request, use it 
00526                          */
00527                         break;
00528                     }
00529                 }
00530             }
00531             if (!row) {
00532                 table_info->colnum++;
00533                 if (table_info->colnum <= table_reg_info->max_column) {
00534                     row = table->first_row;
00535                 }
00536             }
00537             if (row) {
00538                 valid_request = 1;
00539                 netsnmp_request_add_list_data(request,
00540                                               netsnmp_create_data_list
00541                                               (TABLE_DATA_ROW, row,
00542                                                NULL));
00543                 /*
00544                  * Set the name appropriately, so we can pass this
00545                  *  request on as a simple GET request
00546                  */
00547                 netsnmp_table_data_build_result(reginfo, reqinfo, request,
00548                                                 row,
00549                                                 table_info->colnum,
00550                                                 ASN_NULL, NULL, 0);
00551             } else {            /* no decent result found.  Give up. It's beyond us. */
00552                 request->processed = 1;
00553             }
00554             break;
00555 
00556         case MODE_GET:
00557             if (request->requestvb->type != ASN_NULL)
00558                 continue;
00559             /*
00560              * find the row in question 
00561              */
00562             if (request->requestvb->name_length < (reginfo->rootoid_len + 3)) { /* table.entry.column... */
00563                 /*
00564                  * request too short 
00565                  */
00566                 netsnmp_set_request_error(reqinfo, request,
00567                                           SNMP_NOSUCHINSTANCE);
00568                 break;
00569             } else if (NULL ==
00570                        (row =
00571                         netsnmp_table_data_get_from_oid(table,
00572                                                         request->
00573                                                         requestvb->name +
00574                                                         reginfo->
00575                                                         rootoid_len + 2,
00576                                                         request->
00577                                                         requestvb->
00578                                                         name_length -
00579                                                         reginfo->
00580                                                         rootoid_len -
00581                                                         2))) {
00582                 /*
00583                  * no such row 
00584                  */
00585                 netsnmp_set_request_error(reqinfo, request,
00586                                           SNMP_NOSUCHINSTANCE);
00587                 break;
00588             } else {
00589                 valid_request = 1;
00590                 netsnmp_request_add_list_data(request,
00591                                               netsnmp_create_data_list
00592                                               (TABLE_DATA_ROW, row,
00593                                                NULL));
00594             }
00595             break;
00596 
00597         case MODE_SET_RESERVE1:
00598             valid_request = 1;
00599             if (NULL !=
00600                 (row =
00601                  netsnmp_table_data_get_from_oid(table,
00602                                                  request->requestvb->name +
00603                                                  reginfo->rootoid_len + 2,
00604                                                  request->requestvb->
00605                                                  name_length -
00606                                                  reginfo->rootoid_len -
00607                                                  2))) {
00608                 netsnmp_request_add_list_data(request,
00609                                               netsnmp_create_data_list
00610                                               (TABLE_DATA_ROW, row,
00611                                                NULL));
00612             }
00613             break;
00614 
00615         case MODE_SET_RESERVE2:
00616         case MODE_SET_ACTION:
00617         case MODE_SET_COMMIT:
00618         case MODE_SET_FREE:
00619         case MODE_SET_UNDO:
00620             valid_request = 1;
00621 
00622         }
00623     }
00624 
00625     if (valid_request &&
00626        (reqinfo->mode == MODE_GETNEXT || reqinfo->mode == MODE_GETBULK)) {
00627         /*
00628          * If this is a GetNext or GetBulk request, then we've identified
00629          *  the row that ought to include the appropriate next instance.
00630          *  Convert the request into a Get request, so that the lower-level
00631          *  handlers don't need to worry about skipping on, and call these
00632          *  handlers ourselves (so we can undo this again afterwards).
00633          */
00634         oldmode = reqinfo->mode;
00635         reqinfo->mode = MODE_GET;
00636         result = netsnmp_call_next_handler(handler, reginfo, reqinfo,
00637                                          requests);
00638         reqinfo->mode = oldmode;
00639         handler->flags |= MIB_HANDLER_AUTO_NEXT_OVERRIDE_ONCE;
00640         return result;
00641     }
00642     else
00643         /* next handler called automatically - 'AUTO_NEXT' */
00644         return SNMP_ERR_NOERROR;
00645 }
00646 
00648 netsnmp_table_data *
00649 netsnmp_extract_table(netsnmp_request_info *request)
00650 {
00651     return (netsnmp_table_data *)
00652                 netsnmp_request_get_list_data(request, TABLE_DATA_TABLE);
00653 }
00654 
00656 netsnmp_table_row *
00657 netsnmp_extract_table_row(netsnmp_request_info *request)
00658 {
00659     return (netsnmp_table_row *) netsnmp_request_get_list_data(request,
00660                                                                TABLE_DATA_ROW);
00661 }
00662 
00665 void           *
00666 netsnmp_extract_table_row_data(netsnmp_request_info *request)
00667 {
00668     netsnmp_table_row *row;
00669     row = (netsnmp_table_row *) netsnmp_extract_table_row(request);
00670     if (row)
00671         return row->data;
00672     else
00673         return NULL;
00674 }
00675 
00677 NETSNMP_INLINE void
00678 netsnmp_insert_table_row(netsnmp_request_info *request,
00679                          netsnmp_table_row *row)
00680 {
00681     netsnmp_request_info       *req;
00682     netsnmp_table_request_info *table_info = NULL;
00683     netsnmp_variable_list      *this_index = NULL;
00684     netsnmp_variable_list      *that_index = NULL;
00685     oid      base_oid[] = {0, 0};       /* Make sure index OIDs are legal! */
00686     oid      this_oid[MAX_OID_LEN];
00687     oid      that_oid[MAX_OID_LEN];
00688     size_t   this_oid_len, that_oid_len;
00689 
00690     if (!request)
00691         return;
00692 
00693     /*
00694      * We'll add the new row information to any request
00695      * structure with the same index values as the request
00696      * passed in (which includes that one!).
00697      *
00698      * So construct an OID based on these index values.
00699      */
00700 
00701     table_info = netsnmp_extract_table_info(request);
00702     this_index = table_info->indexes;
00703     build_oid_noalloc(this_oid, MAX_OID_LEN, &this_oid_len,
00704                       base_oid, 2, this_index);
00705 
00706     /*
00707      * We need to look through the whole of the request list
00708      * (as received by the current handler), as there's no
00709      * guarantee that this routine will be called by the first
00710      * varbind that refers to this row.
00711      *   In particular, a RowStatus controlled row creation
00712      * may easily occur later in the variable list.
00713      *
00714      * So first, we rewind to the head of the list....
00715      */
00716     for (req=request; req->prev; req=req->prev)
00717         ;
00718 
00719     /*
00720      * ... and then start looking for matching indexes
00721      * (by constructing OIDs from these index values)
00722      */
00723     for (; req; req=req->next) {
00724         table_info = netsnmp_extract_table_info(req);
00725         that_index = table_info->indexes;
00726         build_oid_noalloc(that_oid, MAX_OID_LEN, &that_oid_len,
00727                           base_oid, 2, that_index);
00728       
00729         /*
00730          * This request has the same index values,
00731          * so add the newly-created row information.
00732          */
00733         if (snmp_oid_compare(this_oid, this_oid_len,
00734                              that_oid, that_oid_len) == 0) {
00735             netsnmp_request_add_list_data(req,
00736                 netsnmp_create_data_list(TABLE_DATA_ROW, row, NULL));
00737         }
00738     }
00739 }
00740 
00741 /* builds a result given a row, a varbind to set and the data */
00742 int
00743 netsnmp_table_data_build_result(netsnmp_handler_registration *reginfo,
00744                                 netsnmp_agent_request_info *reqinfo,
00745                                 netsnmp_request_info *request,
00746                                 netsnmp_table_row *row,
00747                                 int column,
00748                                 u_char type,
00749                                 u_char * result_data,
00750                                 size_t result_data_len)
00751 {
00752     oid             build_space[MAX_OID_LEN];
00753 
00754     if (!reginfo || !reqinfo || !request)
00755         return SNMPERR_GENERR;
00756 
00757     if (reqinfo->mode == MODE_GETNEXT || reqinfo->mode == MODE_GETBULK) {
00758         /*
00759          * only need to do this for getnext type cases where oid is changing 
00760          */
00761         memcpy(build_space, reginfo->rootoid,   /* registered oid */
00762                reginfo->rootoid_len * sizeof(oid));
00763         build_space[reginfo->rootoid_len] = 1;  /* entry */
00764         build_space[reginfo->rootoid_len + 1] = column; /* column */
00765         memcpy(build_space + reginfo->rootoid_len + 2,  /* index data */
00766                row->index_oid, row->index_oid_len * sizeof(oid));
00767         snmp_set_var_objid(request->requestvb, build_space,
00768                            reginfo->rootoid_len + 2 + row->index_oid_len);
00769     }
00770     snmp_set_var_typed_value(request->requestvb, type,
00771                              result_data, result_data_len);
00772     return SNMPERR_SUCCESS;     /* WWWXXX: check for bounds */
00773 }
00774 
00775 
00776 /* ==================================
00777  *
00778  * Table Data API: Row operations
00779  *     (table-independent rows)
00780  *
00781  * ================================== */
00782 
00784 netsnmp_table_row *
00785 netsnmp_table_data_get_first_row(netsnmp_table_data *table)
00786 {
00787     if (!table)
00788         return NULL;
00789     return table->first_row;
00790 }
00791 
00793 netsnmp_table_row *
00794 netsnmp_table_data_get_next_row(netsnmp_table_data *table,
00795                                 netsnmp_table_row  *row)
00796 {
00797     if (!row)
00798         return NULL;
00799     return row->next;
00800 }
00801 
00803 netsnmp_table_row *
00804 netsnmp_table_data_get(netsnmp_table_data *table,
00805                        netsnmp_variable_list * indexes)
00806 {
00807     oid             searchfor[MAX_OID_LEN];
00808     size_t          searchfor_len = MAX_OID_LEN;
00809 
00810     build_oid_noalloc(searchfor, MAX_OID_LEN, &searchfor_len, NULL, 0,
00811                       indexes);
00812     return netsnmp_table_data_get_from_oid(table, searchfor,
00813                                            searchfor_len);
00814 }
00815 
00817 netsnmp_table_row *
00818 netsnmp_table_data_get_from_oid(netsnmp_table_data *table,
00819                                 oid * searchfor, size_t searchfor_len)
00820 {
00821     netsnmp_table_row *row;
00822     if (!table)
00823         return NULL;
00824 
00825     for (row = table->first_row; row != NULL; row = row->next) {
00826         if (row->index_oid &&
00827             snmp_oid_compare(searchfor, searchfor_len,
00828                              row->index_oid, row->index_oid_len) == 0)
00829             return row;
00830     }
00831     return NULL;
00832 }
00833 
00834 int
00835 netsnmp_table_data_num_rows(netsnmp_table_data *table)
00836 {
00837     int i=0;
00838     netsnmp_table_row *row;
00839     if (!table)
00840         return 0;
00841     for (row = table->first_row; row; row = row->next) {
00842         i++;
00843     }
00844     return i;
00845 }
00846 
00847     /* =====================================
00848      * Generic API - mostly renamed wrappers
00849      * ===================================== */
00850 
00851 netsnmp_table_row *
00852 netsnmp_table_data_row_first(netsnmp_table_data *table)
00853 {
00854     return netsnmp_table_data_get_first_row(table);
00855 }
00856 
00857 netsnmp_table_row *
00858 netsnmp_table_data_row_get(  netsnmp_table_data *table,
00859                              netsnmp_table_row  *row)
00860 {
00861     if (!table || !row)
00862         return NULL;
00863     return netsnmp_table_data_get_from_oid(table, row->index_oid,
00864                                                   row->index_oid_len);
00865 }
00866 
00867 netsnmp_table_row *
00868 netsnmp_table_data_row_next( netsnmp_table_data *table,
00869                              netsnmp_table_row  *row)
00870 {
00871     return netsnmp_table_data_get_next_row(table, row);
00872 }
00873 
00874 netsnmp_table_row *
00875 netsnmp_table_data_row_get_byoid( netsnmp_table_data *table,
00876                                   oid *instance, size_t len)
00877 {
00878     return netsnmp_table_data_get_from_oid(table, instance, len);
00879 }
00880 
00881 netsnmp_table_row *
00882 netsnmp_table_data_row_next_byoid(netsnmp_table_data *table,
00883                                   oid *instance, size_t len)
00884 {
00885     netsnmp_table_row *row;
00886 
00887     if (!table || !instance)
00888         return NULL;
00889     
00890     for (row = table->first_row; row; row = row->next) {
00891         if (snmp_oid_compare(row->index_oid,
00892                              row->index_oid_len,
00893                              instance, len) > 0)
00894             return row;
00895     }
00896     return NULL;
00897 }
00898 
00899 netsnmp_table_row *
00900 netsnmp_table_data_row_get_byidx( netsnmp_table_data    *table,
00901                                   netsnmp_variable_list *indexes)
00902 {
00903     return netsnmp_table_data_get(table, indexes);
00904 }
00905 
00906 netsnmp_table_row *
00907 netsnmp_table_data_row_next_byidx(netsnmp_table_data    *table,
00908                                   netsnmp_variable_list *indexes)
00909 {
00910     oid    instance[MAX_OID_LEN];
00911     size_t len    = MAX_OID_LEN;
00912 
00913     if (!table || !indexes)
00914         return NULL;
00915 
00916     build_oid_noalloc(instance, MAX_OID_LEN, &len, NULL, 0, indexes);
00917     return netsnmp_table_data_row_next_byoid(table, instance, len);
00918 }
00919 
00920 int
00921 netsnmp_table_data_row_count(netsnmp_table_data *table)
00922 {
00923     return netsnmp_table_data_num_rows(table);
00924 }
00925 
00926 
00927 /* ==================================
00928  *
00929  * Table Data API: Row operations
00930  *     (table-specific rows)
00931  *
00932  * ================================== */
00933 
00934 void *
00935 netsnmp_table_data_entry_first(netsnmp_table_data *table)
00936 {
00937     netsnmp_table_row *row =
00938         netsnmp_table_data_get_first_row(table);
00939     return (row ? row->data : NULL );
00940 }
00941 
00942 void *
00943 netsnmp_table_data_entry_get(  netsnmp_table_data *table,
00944                                netsnmp_table_row  *row)
00945 {
00946     return (row ? row->data : NULL );
00947 }
00948 
00949 void *
00950 netsnmp_table_data_entry_next( netsnmp_table_data *table,
00951                                netsnmp_table_row  *row)
00952 {
00953     row =
00954         netsnmp_table_data_row_next(table, row);
00955     return (row ? row->data : NULL );
00956 }
00957 
00958 void *
00959 netsnmp_table_data_entry_get_byidx( netsnmp_table_data    *table,
00960                                     netsnmp_variable_list *indexes)
00961 {
00962     netsnmp_table_row *row =
00963         netsnmp_table_data_row_get_byidx(table, indexes);
00964     return (row ? row->data : NULL );
00965 }
00966 
00967 void *
00968 netsnmp_table_data_entry_next_byidx(netsnmp_table_data    *table,
00969                                     netsnmp_variable_list *indexes)
00970 {
00971     netsnmp_table_row *row =
00972         netsnmp_table_data_row_next_byidx(table, indexes);
00973     return (row ? row->data : NULL );
00974 }
00975 
00976 void *
00977 netsnmp_table_data_entry_get_byoid( netsnmp_table_data *table,
00978                                     oid *instance, size_t len)
00979 {
00980     netsnmp_table_row *row =
00981         netsnmp_table_data_row_get_byoid(table, instance, len);
00982     return (row ? row->data : NULL );
00983 }
00984 
00985 void *
00986 netsnmp_table_data_entry_next_byoid(netsnmp_table_data *table,
00987                                     oid *instance, size_t len)
00988 {
00989     netsnmp_table_row *row =
00990         netsnmp_table_data_row_next_byoid(table, instance, len);
00991     return (row ? row->data : NULL );
00992 }
00993 
00994     /* =====================================
00995      * Generic API - mostly renamed wrappers
00996      * ===================================== */
00997 
00998 /* ==================================
00999  *
01000  * Table Data API: Index operations
01001  *
01002  * ================================== */
01003 

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