Logo
Home page Net-SNMP

Archive Search:

Require all words?

Site Search:
Google
ttest.c Source File
Main Page   Modules   Data Structures   File List   Related Pages  

ttest.c

00001 /*
00002  * table.c 
00003  */
00004 
00005 #include <config.h>
00006 
00007 #if HAVE_STRING_H
00008 #include <string.h>
00009 #else
00010 #include <strings.h>
00011 #endif
00012 #include <assert.h>
00013 
00014 #include "mibincl.h"
00015 #include "tools.h"
00016 #include "snmp_agent.h"
00017 #include "table.h"
00018 
00019 #if HAVE_DMALLOC_H
00020 #include <dmalloc.h>
00021 #endif
00022 
00023 
00024 mib_handler    *
00025 get_table_handler(table_registration_info * tabreq)
00026 {
00027     mib_handler    *ret = NULL;
00028 
00029     if (!tabreq) {
00030         snmp_log(LOG_INFO, "get_table_handler(NULL) called\n");
00031         return NULL;
00032     }
00033 
00034     ret = create_handler("table", table_helper_handler);
00035     if (ret) {
00036         ret->myvoid = (void *) tabreq;
00037         tabreq->number_indexes = count_varbinds(tabreq->indexes);
00038     }
00039     return ret;
00040 }
00041 
00042 
00043 int
00044 register_table(handler_registration * reginfo,
00045                table_registration_info * tabreq)
00046 {
00047     inject_handler(reginfo, get_table_handler(tabreq));
00048     return register_handler(reginfo);
00049 }
00050 
00051 static void
00052 table_helper_cleanup(agent_request_info * reqinfo, request_info * request,
00053                      int status)
00054 {
00055 
00056     set_request_error(reqinfo, request, status);
00057     if (request->parent_data) {
00058         snmp_free_varbind(((table_request_info *) request->parent_data)->
00059                           indexes);
00060         free(request->parent_data);
00061         request->parent_data = NULL;
00062     }
00063 }
00064 
00065 
00066 unsigned int
00067 closest_column(unsigned int current, column_info * valid_columns)
00068 {
00069     unsigned int    closest = 0;
00070     char            done = 0;
00071     char            idx;
00072     assert(valid_columns != NULL);
00073 
00074     do {
00075 
00076         if (valid_columns->isRange) {
00077 
00078             if (current < valid_columns->details.range[0]) {
00079                 if (valid_columns->details.range[0] < closest) {
00080                     closest = valid_columns->details.range[0];
00081                 }
00082             } else if (current <= valid_columns->details.range[1]) {
00083                 closest = current;
00084                 done = 1;       /* can not get any closer! */
00085             }
00086 
00087         } /* range */
00088         else {                  /* list */
00089 
00090             if (current < valid_columns->details.list[0]) {
00091                 if (valid_columns->details.list[0] < closest)
00092                     closest = valid_columns->details.list[0];
00093                 continue;
00094             }
00095 
00096             if (current >
00097                 valid_columns->details.list[valid_columns->list_count])
00098                 continue;       /* not in list range. */
00099 
00100             for (idx = 0; idx < valid_columns->list_count; ++idx) {
00101                 if (current == valid_columns->details.list[idx]) {
00102                     closest = current;
00103                     done = 1;   /* can not get any closer! */
00104                     break;      /* for */
00105                 } else if (current < valid_columns->details.list[idx]) {
00106                     if (valid_columns->details.list[idx] < closest)
00107                         closest = valid_columns->details.list[idx];
00108                     break;      /* list should be sorted */
00109                 }
00110             }                   /* for */
00111 
00112         }                       /* list */
00113 
00114         valid_columns = valid_columns->next;
00115 
00116     } while (!done && valid_columns);
00117 
00118     return closest;
00119 }
00120 
00121 int
00122 table_helper_handler(mib_handler * handler,
00123                      handler_registration * reginfo,
00124                      agent_request_info * reqinfo, request_info * requests)
00125 {
00126 
00127     request_info   *request;
00128 
00129     table_registration_info *tbl_info;
00130     int             oid_index_pos = reginfo->rootoid_len + 2;
00131     int             oid_column_pos = reginfo->rootoid_len + 1;
00132     int             tmp_idx, tmp_len;
00133     int             incomplete, out_of_range;
00134     int             status = SNMP_ERR_NOERROR, need_processing = 0;
00135     oid            *tmp_name;
00136     table_request_info *tbl_req_info;
00137     struct variable_list *vb;
00138 
00139     tbl_info = (table_registration_info *) handler->myvoid;
00140 
00141     if ((!handler->myvoid) || (!tbl_info->indexes)) {
00142         snmp_log(LOG_INFO, "improperly registered table found\n");
00143 
00144         /*
00145          * XXX-rks: unregister table? 
00146          */
00147         return SNMP_ERR_GENERR;
00148     }
00149 
00150     /*
00151      * * if the agent request info has a state reference, then * this is a 
00152      * later pass of a set request and we can * skip all the lookup stuff. 
00153      */
00154     if (reqinfo->state_reference) {
00155         if (MODE_IS_SET(reqinfo->mode)) {
00156             return call_next_handler(handler, reginfo, reqinfo, requests);
00157         } else {
00158 #warning "XXX-rks: memory leak. add cleanup handler?"
00159             reqinfo->state_reference = NULL;
00160         }
00161     }
00162 
00163 
00164     /*
00165      * loop through requests
00166      */
00167 
00168     DEBUGMSGTL(("helper:table", "Got request:\n"));
00169     for (request = requests; request; request = request->next) {
00170         struct variable_list *var = request->requestvb;
00171 
00172         assert(request->parent_data == NULL);
00173 
00174         DEBUGMSGTL(("helper:table", "  oid:"));
00175         DEBUGMSGOID(("helper:table", var->name, var->name_length));
00176         DEBUGMSG(("helper:table", "\n"));
00177 
00178         if (request->status)
00179             continue;
00180         ++need_processing;
00181 
00182         /*
00183          * this should probably be handled further up 
00184          */
00185         if ((reqinfo->mode == MODE_GET) && (var->type != ASN_NULL)) {   /* valid 
00186                                                                          * request 
00187                                                                          * if 
00188                                                                          * ASN_NULL 
00189                                                                          */
00190             DEBUGMSGTL(("helper:table",
00191                         "  GET var type is not ASN_NULL\n"));
00192             set_request_error(reqinfo, request, SNMP_ERR_WRONGTYPE);
00193             continue;
00194         }
00195 
00196         /*
00197          * check to make sure its in table range
00198          */
00199 
00200         out_of_range = 0;
00201         /*
00202          * if our root oid i > var->name and this is not a GETNEXT, 
00203          */
00204         /*
00205          * then the oid is out of range 
00206          */
00207         if (snmp_oid_compare(reginfo->rootoid, reginfo->rootoid_len,
00208                              var->name, reginfo->rootoid_len) > 0) {
00209             if (reqinfo->mode == MODE_GETNEXT) {
00210                 if (var->name != var->name_loc)
00211                     free(var->name);
00212                 snmp_set_var_objid(var, reginfo->rootoid,
00213                                    reginfo->rootoid_len);
00214             } else {
00215                 DEBUGMSGTL(("helper:table", "  oid is out of range.\n"));
00216                 out_of_range = 1;
00217             }
00218         }
00219         /*
00220          * if var->name is longer than the root, make sure it is 
00221          */
00222         /*
00223          * table.1 (table.ENTRY).  
00224          */
00225         else if ((var->name_length > reginfo->rootoid_len) &&
00226                  (var->name[reginfo->rootoid_len] != 1)) {
00227             if ((var->name[reginfo->rootoid_len] < 1) &&
00228                 (reqinfo->mode == MODE_GETNEXT)) {
00229                 var->name[reginfo->rootoid_len] = 1;
00230                 var->name_length = reginfo->rootoid_len;
00231             } else {
00232                 out_of_range = 1;
00233                 DEBUGMSGTL(("helper:table", "  oid is out of range.\n"));
00234             }
00235         }
00236         /*
00237          * if it is not in range, then remove it from the request list 
00238          */
00239         /*
00240          * because we can't process it. If the request is not a GETNEXT 
00241          */
00242         /*
00243          * then set the error to NOSUCHOBJECT so nobody else wastes time
00244          */
00245         /*
00246          * trying to process it.  
00247          */
00248         if (out_of_range) {
00249             DEBUGMSGTL(("helper:table", "  Not processed.\n"));
00250             if (reqinfo->mode != MODE_GETNEXT) {
00251                 table_helper_cleanup(reqinfo, request,
00252                                      SNMP_ERR_NOSUCHNAME);
00253             }
00254             continue;
00255         }
00256 
00257 
00258         /*
00259          * Check column ranges; set-up to pull out indexes from OID.
00260          */
00261 
00262         incomplete = 0;
00263         tbl_req_info = SNMP_MALLOC_TYPEDEF(table_request_info);
00264         tbl_req_info->indexes = snmp_clone_varbind(tbl_info->indexes);
00265         tbl_req_info->number_indexes = 0;       /* none yet */
00266         if (var->name_length > oid_column_pos) {
00267             if (var->name[oid_column_pos] < tbl_info->min_column) {
00268                 /*
00269                  * fix column, truncate useless index info 
00270                  */
00271                 var->name_length = oid_column_pos;
00272                 tbl_req_info->colnum = tbl_info->min_column;
00273             } else if (var->name[oid_column_pos] > tbl_info->max_column) {
00274                 /*
00275                  * this is out of range...  remove from requests, free
00276                  * memory 
00277                  */
00278                 DEBUGMSGTL(("helper:table",
00279                             "  oid is out of range. Not processed.\n"));
00280                 if (reqinfo->mode != MODE_GETNEXT) {
00281                     table_helper_cleanup(reqinfo, request,
00282                                          SNMP_ERR_NOSUCHNAME);
00283                 }
00284                 continue;
00285             }
00286             /*
00287              * use column verification 
00288              */
00289             else if (tbl_info->valid_columns) {
00290                 tbl_req_info->colnum =
00291                     closest_column(var->name[oid_column_pos],
00292                                    tbl_info->valid_columns);
00293                 if (tbl_req_info->colnum == 0)
00294                     continue;
00295                 if (tbl_req_info->colnum != var->name[oid_column_pos]) {
00296                     /*
00297                      * different column! truncate useless index info 
00298                      */
00299                     var->name_length = oid_column_pos;
00300                 }
00301             }
00302             /*
00303              * var->name_length may have changed - check again 
00304              */
00305             if (var->name_length <= oid_column_pos) {   /* none available */
00306                 tbl_req_info->index_oid_len = 0;
00307             } else {
00308                 tbl_req_info->colnum = var->name[oid_column_pos];
00309                 tbl_req_info->index_oid_len =
00310                     var->name_length - oid_index_pos;
00311                 assert(tbl_req_info->index_oid_len < MAX_OID_LEN);
00312                 memcpy(tbl_req_info->index_oid, &var->name[oid_index_pos],
00313                        tbl_req_info->index_oid_len * sizeof(oid));
00314                 tmp_name = tbl_req_info->index_oid;
00315             }
00316         }
00317         if (tbl_req_info->index_oid_len == 0) {
00318             incomplete = 1;
00319             tmp_len = -1;
00320         } else
00321             tmp_len = tbl_req_info->index_oid_len;
00322 
00323 
00324         /*
00325          * for each index type, try to extract the index from var->name
00326          */
00327 
00328         for (tmp_idx = 0, vb = tbl_req_info->indexes;
00329              tmp_idx < tbl_info->number_indexes;
00330              ++tmp_idx, vb = vb->next_variable) {
00331             if (incomplete && tmp_len) {
00332                 /*
00333                  * incomplete/illegal OID, set up dummy 0 to parse 
00334                  */
00335                 DEBUGMSGTL(("helper:table",
00336                             "  oid indexes not complete.\n"));
00337                 /*
00338                  * no sense in trying anymore if this is a GET/SET. 
00339                  */
00340                 if (reqinfo->mode != MODE_GETNEXT) {
00341                     table_helper_cleanup(reqinfo, requests,
00342                                          SNMP_ERR_NOSUCHNAME);
00343                 }
00344                 tmp_len = 0;
00345                 tmp_name = (oid *) & tmp_len;
00346             }
00347             /*
00348              * try and parse current index 
00349              */
00350             if (parse_one_oid_index(&tmp_name, &tmp_len,
00351                                     vb, 1) != SNMPERR_SUCCESS) {
00352                 incomplete = 1;
00353                 tmp_len = -1;   /* is this necessary? Better safe than
00354                                  * sorry */
00355             } else {
00356                 /*
00357                  * do not count incomplete indexes 
00358                  */
00359                 if (incomplete)
00360                     continue;
00361                 ++tbl_req_info->number_indexes; /* got one ok */
00362                 if (tmp_len <= 0) {
00363                     incomplete = 1;
00364                     tmp_len = -1;       /* is this necessary? Better safe
00365                                          * than sorry */
00366                 }
00367             }
00368         }                       /* for loop */
00369 
00370 
00371         /*
00372          * do we have sufficent index info to continue?
00373          */
00374 
00375         if ((reqinfo->mode != MODE_GETNEXT) &&
00376             ((tbl_req_info->number_indexes != tbl_info->number_indexes) ||
00377              (tmp_len != -1))) {
00378             table_helper_cleanup(reqinfo, request, SNMP_ERR_NOSUCHNAME);
00379         }
00380 
00381         DEBUGIF("helper:table") {
00382             int             count;
00383             char            buf[SPRINT_MAX_LEN];
00384             DEBUGMSGTL(("helper:table", "  column: %d, indexes: %d\n",
00385                         tbl_req_info->colnum,
00386                         tbl_req_info->number_indexes));
00387             for (vb = tbl_req_info->indexes, count = 0;
00388                  vb && count < tbl_info->number_indexes;
00389                  count++, vb = vb->next_variable) {
00390                 sprint_by_type(buf, vb, 0, 0, 0);
00391                 DEBUGMSGTL(("helper:table",
00392                             "    index: type=%d, value=%s\n", vb->type,
00393                             buf));
00394             }
00395         }
00396 
00397         /*
00398          * save table_req_info 
00399          */
00400         request->parent_data = (void *) tbl_req_info;
00401 
00402     }                           /* for each request */
00403 
00404 
00405     /*
00406      * * call our child access function 
00407      */
00408     if (need_processing)
00409         status = call_next_handler(handler, reginfo, reqinfo, requests);
00410 
00411     return status;
00412 }
00413 
00414 int
00415 table_build_oid(handler_registration * reginfo,
00416                 request_info * reqinfo, table_request_info * table_info)
00417 {
00418     oid             tmpoid[MAX_OID_LEN];
00419     struct variable_list *var;
00420 
00421     if (!reginfo || !reqinfo || !table_info)
00422         return SNMPERR_GENERR;
00423 
00424     memcpy(tmpoid, reginfo->rootoid, reginfo->rootoid_len * sizeof(oid));
00425     tmpoid[reginfo->rootoid_len] = 1;   /* .Entry */
00426     tmpoid[reginfo->rootoid_len + 1] = table_info->colnum;      /* .column 
00427                                                                  */
00428 
00429     var = reqinfo->requestvb;
00430     if (build_oid(&var->name, &var->name_length,
00431                   tmpoid, reginfo->rootoid_len + 2, table_info->indexes)
00432         != SNMPERR_SUCCESS)
00433         return SNMPERR_GENERR;
00434 
00435     return SNMPERR_SUCCESS;
00436 }
00437 
00438 int
00439 table_build_oid_from_index(handler_registration * reginfo,
00440                            request_info * reqinfo,
00441                            table_request_info * table_info)
00442 {
00443     oid             tmpoid[MAX_OID_LEN];
00444     struct variable_list *var;
00445     int             len;
00446 
00447     if (!reginfo || !reqinfo || !table_info)
00448         return SNMPERR_GENERR;
00449 
00450     var = reqinfo->requestvb;
00451     len = reginfo->rootoid_len;
00452     memcpy(tmpoid, reginfo->rootoid, len * sizeof(oid));
00453     tmpoid[len++] = 1;          /* .Entry */
00454     tmpoid[len++] = table_info->colnum; /* .column */
00455     memcpy(&tmpoid[len], table_info->index_oid,
00456            table_info->index_oid_len * sizeof(oid));
00457     len += table_info->index_oid_len;
00458     snmp_clone_mem((void **) &var->name, tmpoid, len * sizeof(oid));
00459     var->name_length = len;
00460 
00461     return SNMPERR_SUCCESS;
00462 }
00463 
00464 int
00465 table_build_result(handler_registration * reginfo,
00466                    request_info * reqinfo,
00467                    table_request_info * table_info, u_char type,
00468                    u_char * result, size_t result_len)
00469 {
00470 
00471     struct variable_list *var;
00472 
00473     if (!reqinfo || !table_info)
00474         return SNMPERR_GENERR;
00475 
00476     var = reqinfo->requestvb;
00477 
00478     if (var->name != var->name_loc)
00479         free(var->name);
00480     var->name = NULL;
00481 
00482     if (table_build_oid(reginfo, reqinfo, table_info) != SNMPERR_SUCCESS)
00483         return SNMPERR_GENERR;
00484 
00485     snmp_set_var_typed_value(var, type, result, result_len);
00486 
00487     return SNMPERR_SUCCESS;
00488 }
00489 
00490 int
00491 update_variable_list_from_index(table_request_info * tri)
00492 {
00493     return parse_oid_indexes(tri->index_oid, tri->index_oid_len,
00494                              tri->indexes);
00495 }
00496 
00497 int
00498 update_indexes_from_variable_list(table_request_info * tri)
00499 {
00500     return build_oid_noalloc(tri->index_oid, sizeof(tri->index_oid),
00501                              &tri->index_oid_len, NULL, 0, tri->indexes);
00502 }
00503 
00504 /*
00505  * checks the original request against the current data being passed in if 
00506  * its greater than the request oid but less than the current valid
00507  * return, set the current valid return to the new value.
00508  * 
00509  * returns 1 if outvar was replaced with the oid from newvar (success).
00510  * returns 0 if not. 
00511  */
00512 int
00513 check_getnext_reply(request_info * request,
00514                     oid * prefix,
00515                     size_t prefix_len,
00516                     struct variable_list *newvar,
00517                     struct variable_list **outvar)
00518 {
00519     static oid      myname[MAX_OID_LEN];
00520     static int      myname_len;
00521 
00522     build_oid_noalloc(myname, MAX_OID_LEN, &myname_len,
00523                       prefix, prefix_len, newvar);
00524     /*
00525      * is the build of the new indexes less than our current result 
00526      */
00527     if ((!(*outvar) || snmp_oid_compare(myname + prefix_len,
00528                                         myname_len - prefix_len,
00529                                         (*outvar)->name,
00530                                         (*outvar)->name_length) < 0)) {
00531         /*
00532          * and greater than the requested oid 
00533          */
00534         if (snmp_oid_compare(myname, myname_len,
00535                              request->requestvb->name,
00536                              request->requestvb->name_length) > 0) {
00537             /*
00538              * the new result must be better than the old 
00539              */
00540             if (!*outvar)
00541                 *outvar = snmp_clone_varbind(newvar);
00542             snmp_set_var_objid(*outvar, myname, myname_len);
00543 
00544             return 1;
00545         }
00546     }
00547     return 0;
00548 }

Generated on Thu Nov 15 07:36:24 2001 for net-snmp by doxygen1.2.11 written by Dimitri van Heesch, © 1997-2001
[an error occurred while processing this directive] [an error occurred while processing this directive]

Valid CSS!


Last modified: Wednesday, 01-Aug-2018 04:41:28 UTC
For questions regarding web content and site functionality, please write to the net-snmp-users mail list.