## -*- c -*- ###################################################################### ## Do the .h file ###################################################################### @open ${name}.h@ /* * Note: this file originally auto-generated by mib2c using * $Id: mib2c.iterate.conf,v 5.5 2002/12/16 22:50:18 hardaker Exp $ */ #ifndef $name.uc_H #define $name.uc_H /* function declarations */ void init_$name(void); @foreach $i table@ void initialize_table_$i(void); Netsnmp_Node_Handler ${i}_handler; Netsnmp_First_Data_Point ${i}_get_first_data_point; Netsnmp_Next_Data_Point ${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 using * $Id: mib2c.iterate.conf,v 5.5 2002/12/16 22:50:18 hardaker Exp $ */ #include #include #include #include "${name}.h" @foreach $i table@ /** Initialize the $i table by defining its contents and how it's structured */ void initialize_table_$i(void) { static oid ${i}_oid[] = {$i.commaoid}; netsnmp_table_registration_info *table_info; netsnmp_handler_registration *my_handler; netsnmp_iterator_info *iinfo; /* create the table structure itself */ table_info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info); iinfo = SNMP_MALLOC_TYPEDEF(netsnmp_iterator_info); /* if your table is read only, it's easiest to change the HANDLER_CAN_RWRITE definition below to HANDLER_CAN_RONLY */ my_handler = netsnmp_create_handler_registration("$i", ${i}_handler, ${i}_oid, OID_LENGTH(${i}_oid), HANDLER_CAN_RWRITE); if (!my_handler || !table_info || !iinfo) return; /* mallocs failed */ /*************************************************** * Setting up the table's definition */ netsnmp_table_helper_add_indexes(table_info, @foreach $idx index@ $idx.type, /* index: $idx */ @end@ 0); @eval $minv = 0xffffffff@ @eval $maxv = 0@ @foreach $c column@ @if $c.access =~ /(Read|Create)/@ @eval $minv = min($minv, $c.subid)@ @eval $maxv = max($maxv, $c.subid)@ @end@ @end@ table_info->min_column = $minv; table_info->max_column = $maxv; /* iterator access routines */ iinfo->get_first_data_point = ${i}_get_first_data_point; iinfo->get_next_data_point = ${i}_get_next_data_point; iinfo->table_reginfo = table_info; /*************************************************** * registering the table with the master agent */ DEBUGMSGTL(("initialize_table_$i", "Registering table $i as a table iterator\n")); netsnmp_register_table_iterator(my_handler, iinfo); } @end@ /** Initializes 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. */ netsnmp_variable_list * ${i}_get_first_data_point(void **my_loop_context, void **my_data_context, netsnmp_variable_list *put_index_data, netsnmp_iterator_info *mydata) { netsnmp_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. */ netsnmp_variable_list * ${i}_get_next_data_point(void **my_loop_context, void **my_data_context, netsnmp_variable_list *put_index_data, netsnmp_iterator_info *mydata) { netsnmp_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( netsnmp_mib_handler *handler, netsnmp_handler_registration *reginfo, netsnmp_agent_request_info *reqinfo, netsnmp_request_info *requests) { netsnmp_request_info *request; netsnmp_table_request_info *table_info; netsnmp_variable_list *var; for(request = requests; request; request = request->next) { var = request->requestvb; if (request->processed != 0) continue; /* perform anything here that you need to do before each request is processed. */ /* 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 */ *) netsnmp_extract_iterator_context(request); if (/* XXX */ == NULL) { if (reqinfo->mode == MODE_GET) { netsnmp_set_request_error(reqinfo, request, 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 = netsnmp_extract_table_info(request); /* 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) { 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@ @if $c.access =~ /(Read|Create)/@ case COLUMN_$c.uc: snmp_set_var_typed_value(var, $c.type, (u_char *) /* XXX: column data */, /* XXX: column data length */); break; @end@ @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"); } } return SNMP_ERR_NOERROR; }