blob: a38ac20073d9a6e083879443776350518aade6de [file] [log] [blame]
## -*- c -*-
######################################################################
## Do the .h file
######################################################################
@open ${name}.h@
/*
* Note: this file originally auto-generated by mib2c using
* $Id$
*/
#ifndef $name.uc_H
#define $name.uc_H
/** other required module components */
config_require(${name}_access)
config_require(${name}_checkfns)
/* function declarations */
void init_$name(void);
@foreach $i table@
void initialize_table_$i(void);
Netsnmp_Node_Handler ${i}_handler;
@end@
@foreach $i table@
/* column number definitions for table $i */
#include "${name}_columns.h"
@run mib2c.column_defines.conf@
/* enum definions */
#include "${name}_enums.h"
@run mib2c.column_enums.conf@
@end@
#endif /** $name.uc_H */
######################################################################
## Do the .c file
######################################################################
@open ${name}.c@
/*
* Note: this file originally auto-generated by mib2c using
* $Id$
*/
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#include <net-snmp/agent/net-snmp-agent-includes.h>
#include "${name}.h"
#include "${name}_checkfns.h"
#include "${name}_access.h"
static netsnmp_oid_stash_node *undoStorage = NULL;
static netsnmp_oid_stash_node *commitStorage = NULL;
struct undoInfo {
void *ptr;
size_t len;
};
struct commitInfo {
void *data_context;
int have_committed;
int new_row;
};
void
${name}_free_undoInfo(void *vptr) {
struct undoInfo *ui = vptr;
if (!ui)
return;
SNMP_FREE(ui->ptr);
SNMP_FREE(ui);
}
@foreach $i table@
/** Initialize the $i table by defining its contents and how it's structured */
void
initialize_table_$i(void)
{
const oid ${i}_oid[] = {$i.commaoid};
netsnmp_table_registration_info *table_info;
netsnmp_handler_registration *my_handler;
netsnmp_iterator_info *iinfo;
DEBUGMSGTL(("${name}:init", "initializing table $i\n"));
/** create the table registration information structures */
table_info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info);
iinfo = SNMP_MALLOC_TYPEDEF(netsnmp_iterator_info);
my_handler = netsnmp_create_handler_registration("$i",
${i}_handler,
${i}_oid,
OID_LENGTH(${i}_oid),
@if $i.settable@
HANDLER_CAN_RWRITE
@else@
HANDLER_CAN_RONLY
@end@
);
if (!my_handler || !table_info || !iinfo) {
snmp_log(LOG_ERR, "malloc failed in initialize_table_$i");
return; /** Serious error. */
}
/***************************************************
* Setting up the table's definition
*/
netsnmp_table_helper_add_indexes(table_info,
@foreach $idx index@
$idx.type, /** index: $idx */
@end@
0);
/** Define the minimum and maximum accessible columns. This
optimizes retrieval. */
@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;
/** you may wish to set these as well */
#ifdef MAYBE_USE_THESE
iinfo->make_data_context = ${i}_context_convert_function;
iinfo->free_data_context = ${i}_data_free;
/** pick *only* one of these if you use them */
iinfo->free_loop_context = ${i}_loop_free;
iinfo->free_loop_context_at_end = ${i}_loop_free;
#endif
/** tie the two structures together */
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@
/** 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;
struct commitInfo *ci = NULL;
void *data_context = NULL;
/** column and row index encoded portion */
const oid * const suffix =
requests->requestvb->name + reginfo->rootoid_len + 1;
const size_t suffix_len = requests->requestvb->name_length -
(reginfo->rootoid_len + 1);
DEBUGMSGTL(("${name}:handler", "Processing request (%d)\n", reqinfo->mode));
for(request = requests; request; request = request->next) {
var = request->requestvb;
if (request->processed != 0)
continue;
switch (reqinfo->mode) {
case MODE_GET:
data_context = netsnmp_extract_iterator_context(request);
if (data_context == NULL) {
netsnmp_set_request_error(reqinfo, request,
SNMP_NOSUCHINSTANCE);
continue;
}
break;
@if $i.settable@
case MODE_SET_RESERVE1:
data_context = netsnmp_extract_iterator_context(request);
@if !$i.creatable@
if (data_context == NULL) {
netsnmp_set_request_error(reqinfo, request,
SNMP_ERR_NOCREATION);
continue;
}
@end@
break;
default: /* == the other SET modes */
ci = netsnmp_oid_stash_get_data(commitStorage,
suffix+1, suffix_len-1);
break;
@end@
}
/** 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) {
case MODE_GET:
switch(table_info->colnum) {
@foreach $c column@
@if $c.access =~ /(Read|Create)/@
case COLUMN_$c.uc:
{
$c.decl *retval;
size_t retval_len = 0;
retval = get_$c(data_context, &retval_len);
if (retval)
snmp_set_var_typed_value(var, $c.type,
retval,
retval_len);
}
break;
@end@
@end@
default:
/** We shouldn't get here */
snmp_log(LOG_ERR, "problem encountered in ${i}_handler: unknown column\n");
}
break;
@if $i.settable@
case MODE_SET_RESERVE1:
ci = netsnmp_oid_stash_get_data(commitStorage,
suffix+1, suffix_len-1);
if (!ci) {
/** create the commit storage info */
ci = SNMP_MALLOC_STRUCT(commitInfo);
if (!data_context) {
ci->data_context = ${i}_create_data_context(table_info->indexes, table_info->colnum);
ci->new_row = 1;
} else {
ci->data_context = data_context;
}
netsnmp_oid_stash_add_data(&commitStorage,
suffix+1, suffix_len-1, ci);
}
break;
case MODE_SET_RESERVE2:
switch(table_info->colnum) {
@foreach $c column@
@if $c.access =~ /(Write|Create)/@
case COLUMN_$c.uc:
{
$c.decl *retval;
size_t retval_len = 0;
struct undoInfo *ui = NULL;
int ret;
/** first, get the old value */
retval = get_$c(ci->data_context, &retval_len);
if (retval) {
ui = SNMP_MALLOC_STRUCT(undoInfo);
ui->len = retval_len;
ui->ptr = netsnmp_memdup(retval, ui->len);
}
/** check the new value, possibly against the
older value for a valid state transition */
ret = check_$c(request->requestvb->type,
($c.decl *) request->requestvb->val.string,
request->requestvb->val_len,
retval, retval_len);
if (ret != 0) {
netsnmp_set_request_error(reqinfo, request,
ret);
${name}_free_undoInfo(ui);
} else if (ui) {
/** remember information for undo purposes later */
netsnmp_oid_stash_add_data(&undoStorage,
suffix,
suffix_len,
ui);
}
}
break;
@end@
@end@
default:
netsnmp_set_request_error(reqinfo, request,
SNMP_ERR_NOTWRITABLE);
break;
}
break;
case MODE_SET_ACTION:
/** save a variable copy */
switch(table_info->colnum) {
@foreach $c column@
@if $c.access =~ /(Write|Create)/@
case COLUMN_$c.uc:
{
int ret;
ret = set_$c(ci->data_context,
($c.decl *) request->requestvb->val.string,
request->requestvb->val_len);
if (ret) {
netsnmp_set_request_error(reqinfo, request,
ret);
}
@if $c.syntax eq "RowStatus"@
if (*request->requestvb->val.integer ==
RS_DESTROY) {
ci->new_row = -1;
}
@end@
}
break;
@end@
@end@
}
break;
case MODE_SET_COMMIT:
if (!ci->have_committed) {
/** do this once per row only */
${i}_commit_row(&ci->data_context, ci->new_row);
ci->have_committed = 1;
}
break;
case MODE_SET_UNDO:
/** save a variable copy */
switch(table_info->colnum) {
@foreach $c column@
@if $c.access =~ /(Write|Create)/@
case COLUMN_$c.uc:
{
int retval;
struct undoInfo *ui;
ui = netsnmp_oid_stash_get_data(undoStorage,
suffix,
suffix_len);
retval = set_$c(ci->data_context, ui->ptr,
ui->len);
if (retval) {
netsnmp_set_request_error(reqinfo, request,
SNMP_ERR_UNDOFAILED);
}
}
break;
@end@
@end@
}
break;
case MODE_SET_FREE:
break;
@end@
default:
snmp_log(LOG_ERR, "problem encountered in ${i}_handler: unsupported mode\n");
}
}
@if $i.settable@
/** clean up after all requset processing has ended */
switch(reqinfo->mode) {
case MODE_SET_UNDO:
case MODE_SET_FREE:
case MODE_SET_COMMIT:
/** clear out the undo cache */
netsnmp_oid_stash_free(&undoStorage, ${name}_free_undoInfo);
netsnmp_oid_stash_free(&commitStorage, netsnmp_oid_stash_no_free);
}
@end@
return SNMP_ERR_NOERROR;
}
@end@
@run mib2c.check_values.conf@
@run mib2c.access_functions.conf@
@open -@
**********************************************************************
NOTE: The only files you MUST modify should be the following:
${name}_access.c
${name}_access.h
${name}_checkfns_local.h
${name}_checkfns_local.c
**********************************************************************