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