net-snmp 5.7
table_row.c
00001 /*
00002  * table_row.c
00003  *
00004  * Helper for registering single row slices of a shared table
00005  *
00006  * $Id$
00007  */
00008 #define TABLE_ROW_DATA  "table_row"
00009 
00010 #include <net-snmp/net-snmp-config.h>
00011 #include <net-snmp/net-snmp-features.h>
00012 
00013 #if HAVE_STRING_H
00014 #include <string.h>
00015 #else
00016 #include <strings.h>
00017 #endif
00018 
00019 #include <net-snmp/net-snmp-includes.h>
00020 #include <net-snmp/agent/net-snmp-agent-includes.h>
00021 
00022 #include <net-snmp/agent/table.h>
00023 #include <net-snmp/agent/table_container.h>
00024 #include <net-snmp/library/container.h>
00025 #include <net-snmp/library/snmp_assert.h>
00026 
00027 netsnmp_feature_child_of(table_row_all, mib_helpers)
00028 
00029 netsnmp_feature_child_of(table_row_extract, table_row_all)
00030 
00031 
00032 /*
00033  * snmp.h:#define SNMP_MSG_INTERNAL_SET_BEGIN        -1 
00034  * snmp.h:#define SNMP_MSG_INTERNAL_SET_RESERVE1     0 
00035  * snmp.h:#define SNMP_MSG_INTERNAL_SET_RESERVE2     1 
00036  * snmp.h:#define SNMP_MSG_INTERNAL_SET_ACTION       2 
00037  * snmp.h:#define SNMP_MSG_INTERNAL_SET_COMMIT       3 
00038  * snmp.h:#define SNMP_MSG_INTERNAL_SET_FREE         4 
00039  * snmp.h:#define SNMP_MSG_INTERNAL_SET_UNDO         5 
00040  */
00041 
00050 static Netsnmp_Node_Handler _table_row_handler;
00051 static Netsnmp_Node_Handler _table_row_default_handler;
00052 
00053 /**********************************************************************
00054  **********************************************************************
00055  *                                                                    *
00056  *                                                                    *
00057  * PUBLIC Registration functions                                      *
00058  *                                                                    *
00059  *                                                                    *
00060  **********************************************************************
00061  **********************************************************************/
00062 
00063 /* ==================================
00064  *
00065  * Table Row API: Table maintenance
00066  *
00067  * This helper doesn't operate with the complete
00068  *   table, so these routines are not relevant.
00069  *
00070  * ================================== */
00071 
00072 
00073 /* ==================================
00074  *
00075  * Table Row API: MIB maintenance
00076  *
00077  * ================================== */
00078 
00080 netsnmp_mib_handler *
00081 netsnmp_table_row_handler_get(void *row)
00082 {
00083     netsnmp_mib_handler *handler;
00084 
00085     handler = netsnmp_create_handler("table_row",
00086                                      _table_row_handler);
00087     if(NULL == handler) {
00088         snmp_log(LOG_ERR,
00089                  "malloc failure in netsnmp_table_row_register\n");
00090         return NULL;
00091     }
00092 
00093     handler->myvoid = (void*)row;
00094     handler->flags |= MIB_HANDLER_INSTANCE;
00095  /* handler->flags |= MIB_HANDLER_AUTO_NEXT;  ??? */
00096     
00097     return handler;
00098 }
00099 
00100 int
00101 netsnmp_table_row_register(netsnmp_handler_registration *reginfo,
00102                            netsnmp_table_registration_info *tabreg,
00103                            void *row, netsnmp_variable_list *index)
00104 {
00105     netsnmp_handler_registration *reg2;
00106     netsnmp_mib_handler *handler;
00107     oid    row_oid[MAX_OID_LEN];
00108     size_t row_oid_len, len;
00109     char   tmp[SNMP_MAXBUF_MEDIUM];
00110 
00111     if ((NULL == reginfo) || (NULL == reginfo->handler) || (NULL == tabreg)) {
00112         snmp_log(LOG_ERR, "bad param in netsnmp_table_row_register\n");
00113         return SNMPERR_GENERR;
00114     }
00115 
00116         /*
00117          *   The first table_row invoked for a particular table should
00118          * register the full table as well, with a default handler to
00119          * process requests for non-existent (or incomplete) rows.
00120          *
00121          *   Subsequent table_row registrations attempting to set up
00122          * this default handler would fail - preferably silently!
00123          */
00124     snprintf(tmp, sizeof(tmp), "%s_table", reginfo->handlerName);
00125     reg2 = netsnmp_create_handler_registration(
00126               tmp,     _table_row_default_handler,
00127               reginfo->rootoid, reginfo->rootoid_len,
00128               reginfo->modes);
00129     netsnmp_register_table(reg2, tabreg);  /* Ignore return value */
00130 
00131         /*
00132          * Adjust the OID being registered, to take account
00133          * of the indexes and column range provided....
00134          */
00135     row_oid_len = reginfo->rootoid_len;
00136     memcpy( row_oid, (u_char *) reginfo->rootoid, row_oid_len * sizeof(oid));
00137     row_oid[row_oid_len++] = 1;   /* tableEntry */
00138     row_oid[row_oid_len++] = tabreg->min_column;
00139     reginfo->range_ubound  = tabreg->max_column;
00140     reginfo->range_subid   = row_oid_len-1;
00141     build_oid_noalloc(&row_oid[row_oid_len],
00142                       MAX_OID_LEN-row_oid_len, &len, NULL, 0, index);
00143     row_oid_len += len;
00144     free(reginfo->rootoid);
00145     reginfo->rootoid = snmp_duplicate_objid(row_oid, row_oid_len);
00146     reginfo->rootoid_len = row_oid_len;
00147 
00148      
00149         /*
00150          * ... insert a minimal handler ...
00151          */
00152     handler = netsnmp_table_row_handler_get(row);
00153     netsnmp_inject_handler(reginfo, handler );
00154 
00155         /*
00156          * ... and register the row
00157          */
00158     return netsnmp_register_handler(reginfo);
00159 }
00160 
00161 
00163 #ifndef NETSNMP_FEATURE_REMOVE_TABLE_ROW_EXTRACT
00164 void *
00165 netsnmp_table_row_extract(netsnmp_request_info *request)
00166 {
00167     return netsnmp_request_get_list_data(request, TABLE_ROW_DATA);
00168 }
00169 #endif /* NETSNMP_FEATURE_REMOVE_TABLE_ROW_EXTRACT */
00170 
00172 /**********************************************************************
00173  **********************************************************************
00174  *                                                                    *
00175  *                                                                    *
00176  * netsnmp_table_row_helper_handler()                           *
00177  *                                                                    *
00178  *                                                                    *
00179  **********************************************************************
00180  **********************************************************************/
00181 
00182 static int
00183 _table_row_handler(netsnmp_mib_handler          *handler,
00184                    netsnmp_handler_registration *reginfo,
00185                    netsnmp_agent_request_info   *reqinfo,
00186                    netsnmp_request_info         *requests)
00187 {
00188     int             rc = SNMP_ERR_NOERROR;
00189     netsnmp_request_info *req;
00190     void                 *row;
00191 
00193     netsnmp_assert((NULL != handler) && (NULL != handler->myvoid));
00194     netsnmp_assert((NULL != reginfo) && (NULL != reqinfo));
00195 
00196     DEBUGMSGTL(("table_row", "Mode %s, Got request:\n",
00197                 se_find_label_in_slist("agent_mode",reqinfo->mode)));
00198 
00199     /*
00200      * First off, get our pointer from the handler.
00201      * This contains the row that was actually registered.
00202      * Make this available for each of the requests passed in.
00203      */
00204     row = handler->myvoid;
00205     for (req = requests; req; req=req->next)
00206         netsnmp_request_add_list_data(req,
00207                 netsnmp_create_data_list(TABLE_ROW_DATA, row, NULL));
00208 
00209     /*
00210      * Then call the next handler, to actually process the request
00211      */
00212     rc = netsnmp_call_next_handler(handler, reginfo, reqinfo, requests);
00213     if (rc != SNMP_ERR_NOERROR) {
00214         DEBUGMSGTL(("table_row", "next handler returned %d\n", rc));
00215     }
00216 
00217     return rc;
00218 }
00219 
00220 static int
00221 _table_row_default_handler(netsnmp_mib_handler  *handler,
00222                    netsnmp_handler_registration *reginfo,
00223                    netsnmp_agent_request_info   *reqinfo,
00224                    netsnmp_request_info         *requests)
00225 {
00226     netsnmp_request_info       *req;
00227     netsnmp_table_request_info *table_info;
00228     netsnmp_table_registration_info *tabreg;
00229 
00230     tabreg = netsnmp_find_table_registration_info(reginfo);
00231     for ( req=requests; req; req=req->next ) {
00232         table_info = netsnmp_extract_table_info( req );
00233         if (( table_info->colnum >= tabreg->min_column ) ||
00234             ( table_info->colnum <= tabreg->max_column )) {
00235             netsnmp_set_request_error( reqinfo, req, SNMP_NOSUCHINSTANCE );
00236         } else {
00237             netsnmp_set_request_error( reqinfo, req, SNMP_NOSUCHOBJECT );
00238         }
00239     }
00240     return SNMP_ERR_NOERROR;
00241 }
00245 /* ==================================
00246  *
00247  * Table Row API: Row operations
00248  *
00249  * This helper doesn't operate with the complete
00250  *   table, so these routines are not relevant.
00251  *
00252  * ================================== */
00253 
00254 
00255 /* ==================================
00256  *
00257  * Table Row API: Index operations
00258  *
00259  * This helper doesn't operate with the complete
00260  *   table, so these routines are not relevant.
00261  *
00262  * ================================== */
00263