| ## -*- c -*- |
| ###################################################################### |
| ## Do the .h file |
| ###################################################################### |
| @open ${name}.h@ |
| /* Note: this file originally auto-generated by mib2c */ |
| #ifndef $name.uc_H |
| #define $name.uc_H |
| |
| /* function declarations */ |
| void init_$name(void); |
| @foreach $i table@ |
| void initialize_table_$i(void); |
| NodeHandler ${i}_handler; |
| |
| FirstDataPoint ${i}_get_first_data_point; |
| NextDataPoint ${i}_get_next_data_point; |
| @end@ |
| @foreach $i table@ |
| |
| /* column number definitions for table $i */ |
| @foreach $c column@ |
| #define COLUMN_$c.uc $c.subid |
| @end@ |
| @end@ |
| #endif /* $name.uc_H */ |
| ###################################################################### |
| ## Do the .c file |
| ###################################################################### |
| @open ${name}.c@ |
| /* Note: this file originally auto-generated by mib2c */ |
| |
| #include <config.h> |
| |
| #include "mibincl.h" |
| #include "snmp_loging.h" |
| #include <helpers/table.h> |
| #include <helpers/table_iterator.h> |
| #include "${name}.h" |
| |
| @foreach $i table@ |
| /** Initialize the $i table by defining it's contents and how it's structured */ |
| void |
| initialize_table_$i(void) |
| { |
| static oid ${i}_oid[] = {$i.commaoid}; |
| size_t ${i}_oid_len = OID_LENGTH(${i}_oid); |
| table_registration_info *table_info; |
| handler_registration *my_handler; |
| |
| /* create the table structure itself */ |
| table_info = SNMP_MALLOC_TYPEDEF(table_registration_info); |
| |
| /* if your table is read only, it's easiest to change the |
| HANDLER_CAN_RWRITE definition below to HANDLER_CAN_RONLY */ |
| my_handler = create_handler_registration("$i", |
| ${i}_handler, |
| ${i}_oid, |
| sizeof(${i}_oid)/sizeof(oid), |
| HANDLER_CAN_RWRITE); |
| |
| if (!my_handler || !table_info) |
| return; /* mallocs failed */ |
| |
| /*************************************************** |
| * Setting up the table's definition |
| */ |
| @foreach $idx index@ |
| table_helper_add_index(table_info, $idx.type); /* index: $idx */ |
| @end@ |
| |
| @eval $minv = 0xffffffff@ |
| @eval $maxv = 0@ |
| @foreach $c column@ |
| @eval $minv = min($minv, $c.subid)@ |
| @eval $maxv = max($maxv, $c.subid)@ |
| @end@ |
| table_info->min_column = $minv; |
| table_info->max_column = $maxv; |
| table_info->get_first_data_point = ${i}_get_first_data_point; |
| table_info->get_next_data_point = ${i}_get_next_data_point; |
| |
| /*************************************************** |
| * registering the table with the master agent |
| */ |
| DEBUGMSGTL(("initialize_table_$i", |
| "Registering table $i as a table iterator\n")); |
| register_table_iterator(my_handler, table_info); |
| } |
| @end@ |
| |
| /** Initialzies the $name module */ |
| void |
| init_$name(void) |
| { |
| |
| /* here we initialize all the tables we're planning on supporting */ |
| @foreach $i table@ |
| initialize_table_$i(); |
| @end@ |
| } |
| @foreach $i table@ |
| |
| /** returns the first data point within the $i table data. |
| |
| Set the my_loop_context variable to the first data point structure |
| of your choice (from which you can find the next one). This could |
| be anything from the first node in a linked list, to an integer |
| pointer containing the beginning of an array variable. |
| |
| Set the my_data_context variable to something to be returned to |
| you later that will provide you with the data to return in a given |
| row. This could be the same pointer as what my_loop_context is |
| set to, or something different. |
| |
| The put_index_data variable contains a list of snmp variable |
| bindings, one for each index in your table. Set the values of |
| each appropriately according to the data matching the first row |
| and return the put_index_data variable at the end of the function. |
| */ |
| struct variable_list * |
| ${i}_get_first_data_point(void **my_loop_context, void **my_data_context, |
| struct variable_list *put_index_data) { |
| |
| struct variable_list *vptr; |
| |
| *my_loop_context = /* XXX */; |
| *my_data_context = /* XXX */; |
| |
| vptr = put_index_data; |
| |
| @foreach $idx index@ |
| snmp_set_var_value(vptr, (u_char *) /* XXX: $idx data */, /* XXX: length of $idx data */); |
| vptr = vptr->next_variable; |
| @end@ |
| |
| return put_index_data; |
| } |
| |
| /** functionally the same as ${i}_get_first_data_point, but |
| my_loop_context has already been set to a previous value and should |
| be updated to the next in the list. For example, if it was a |
| linked list, you might want to cast it and the return |
| my_loop_context->next. The my_data_context pointer should be set |
| to something you need later and the indexes in put_index_data |
| updated again. */ |
| |
| struct variable_list * |
| ${i}_get_next_data_point(void **my_loop_context, void **my_data_context, |
| struct variable_list *put_index_data) { |
| |
| struct variable_list *vptr; |
| |
| *my_loop_context = /* XXX */; |
| *my_data_context = /* XXX */; |
| |
| vptr = put_index_data; |
| |
| @foreach $idx index@ |
| snmp_set_var_value(vptr, (u_char *) /* XXX: $idx data */, /* XXX: length of $idx data */); |
| vptr = vptr->next_variable; |
| @end@ |
| |
| return put_index_data; |
| } |
| |
| /** handles requests for the $i table, if anything else needs to be done */ |
| int |
| ${i}_handler( |
| mib_handler *handler, |
| handler_registration *reginfo, |
| agent_request_info *reqinfo, |
| request_info *requests) { |
| |
| table_request_info *table_info; |
| struct variable_list *var; |
| |
| while(requests) { |
| var = requests->requestvb; |
| if (requests->processed != 0) |
| continue; |
| |
| /* perform anything here that you need to do. The requests have |
| already been processed by the master table_dataset handler, but |
| this gives you chance to act on the request in some other way |
| if need be. */ |
| |
| /* the following extracts the my_data_context pointer set in |
| the loop functions above. You can then use the results to |
| help return data for the columns of the $i table in question */ |
| /* XXX */ = (/* XXX */ *) extract_iterator_context(requests); |
| if (/* XXX */ == NULL) { |
| if (reqinfo->mode == MODE_GET) { |
| set_request_error(reqinfo, requests, SNMP_NOSUCHINSTANCE); |
| continue; |
| } |
| /* XXX: no row existed, if you support creation and this is a |
| set, start dealing with it here, else continue */ |
| } |
| |
| /* extracts the information about the table from the request */ |
| table_info = extract_table_info(requests); |
| /* table_info->colnum contains the column number requested */ |
| /* table_info->indexes contains a linked list of snmp variable |
| bindings for the indexes of the table. Values in the list |
| have been set corresponding to the indexes of the |
| request */ |
| if (table_info==NULL) { |
| requests = requests->next; |
| continue; |
| } |
| |
| switch(reqinfo->mode) { |
| /* the table_iterator helper should change all GETNEXTs |
| into GETs for you automatically, so you don't have to |
| worry about the GETNEXT case. Only GETs and SETs need |
| to be dealt with here */ |
| case MODE_GET: |
| switch(table_info->colnum) { |
| @foreach $c column@ |
| case COLUMN_$c.uc: |
| snmp_set_var_typed_value(var, $c.type, (u_char *) /* XXX: column data */, /* XXX: column data length */); |
| break; |
| |
| @end@ |
| default: |
| /* We shouldn't get here */ |
| snmp_log(LOG_ERR, "problem encountered in ${i}_handler: unknown column\n"); |
| } |
| break; |
| |
| case MODE_SET_RESERVE1: |
| /* set handling... */ |
| |
| default: |
| snmp_log(LOG_ERR, "problem encountered in ${i}_handler: unsupported mode\n"); |
| } |
| requests = requests->next; |
| } |
| return SNMP_ERR_NOERROR; |
| } |