1713 lines
51 KiB
C
1713 lines
51 KiB
C
############################################################# -*- c -*-
|
|
## generic include for XXX. Do not use directly.
|
|
##
|
|
########################################################################
|
|
@if $m2c_mark_boundary == 1@
|
|
/** START code generated by mfd-interface.m2c */
|
|
@end@
|
|
########################################################################
|
|
##
|
|
########################################################################
|
|
@eval $m2c_processing_type = 'h'@
|
|
@open ${name}_interface.h@
|
|
/*
|
|
* Note: this file originally auto-generated by mib2c
|
|
* using mfd-interface.m2c
|
|
*/
|
|
/** @ingroup interface: Routines to interface to Net-SNMP
|
|
*
|
|
* \warning This code should not be modified, called directly,
|
|
* or used to interpret functionality. It is subject to
|
|
* change at any time.
|
|
*
|
|
* @{
|
|
*/
|
|
@include m2c-internal-warning.m2i@
|
|
##
|
|
@eval $m2c_save = "$name"@
|
|
@eval $name = "${name}_INTERFACE"@
|
|
@include generic-header-top.m2i@
|
|
@eval $name = "$m2c_save"@
|
|
|
|
#include "${name}.h"
|
|
|
|
|
|
/* ********************************************************************
|
|
* Table declarations
|
|
*/
|
|
@foreach $table table@
|
|
@ include m2c_setup_table.m2i@
|
|
|
|
/* PUBLIC interface initialization routine */
|
|
void _${context}_initialize_interface(${context}_registration * user_ctx,
|
|
u_long flags);
|
|
void _${context}_shutdown_interface(${context}_registration * user_ctx);
|
|
|
|
${context}_registration *
|
|
${context}_registration_get( void );
|
|
|
|
${context}_registration *
|
|
${context}_registration_set( ${context}_registration * newreg );
|
|
|
|
netsnmp_container *${context}_container_get( void );
|
|
int ${context}_container_size( void );
|
|
|
|
@ if $m2c_table_settable@
|
|
u_int ${context}_dirty_get( void );
|
|
void ${context}_dirty_set( u_int status );
|
|
|
|
@ end@
|
|
@ if $m2c_data_allocate == 1@
|
|
@ eval $m2c_tmp = "${context}_data *"@
|
|
@ if $m2c_data_init == 1@
|
|
@ eval $m2c_tmp = "$m2c_tmp, void *"@
|
|
@ @end@
|
|
@ elsif $m2c_data_init == 1@
|
|
@ eval $m2c_tmp = "void *"@
|
|
@ else@
|
|
@ eval $m2c_tmp = "void"@
|
|
@ end@
|
|
${context}_rowreq_ctx * ${context}_allocate_rowreq_ctx($m2c_tmp);
|
|
void ${context}_release_rowreq_ctx(${context}_rowreq_ctx *rowreq_ctx);
|
|
|
|
int ${context}_index_to_oid(netsnmp_index *oid_idx,
|
|
${context}_mib_index *mib_idx);
|
|
int ${context}_index_from_oid(netsnmp_index *oid_idx,
|
|
${context}_mib_index *mib_idx);
|
|
|
|
@ if $m2c_table_persistent == 1@
|
|
@ include mfd-persistence.m2i@
|
|
|
|
@ end@
|
|
/*
|
|
* access to certain internals. use with caution!
|
|
*/
|
|
void ${context}_valid_columns_set(netsnmp_column_info *vc);
|
|
|
|
@end@ # for each
|
|
@eval $m2c_save = "$name"@
|
|
@eval $name = "${name}_INTERFACE"@
|
|
@include generic-header-bottom.m2i@
|
|
/** @} */
|
|
@eval $name = "$m2c_save"@
|
|
########################################################################
|
|
########################################################################
|
|
########################################################################
|
|
########################################################################
|
|
########################################################################
|
|
########################################################################
|
|
########################################################################
|
|
##
|
|
@open ${name}_interface.c@
|
|
/*
|
|
* Note: this file originally auto-generated by mib2c
|
|
* using mfd-interface.m2c
|
|
*/
|
|
@include m2c-internal-warning.m2i@
|
|
|
|
@include generic-source-includes.m2i@
|
|
|
|
#include <net-snmp/agent/table_container.h>
|
|
#include <net-snmp/library/container.h>
|
|
|
|
#include "${name}_interface.h"
|
|
|
|
netsnmp_feature_require(baby_steps)
|
|
netsnmp_feature_require(row_merge)
|
|
netsnmp_feature_require(check_all_requests_error)
|
|
|
|
#include <ctype.h>
|
|
|
|
@eval $m2c_processing_type = 'i'@
|
|
@foreach $table table@
|
|
@ include m2c_setup_table.m2i@
|
|
@ include details-table.m2i@
|
|
########################################################################
|
|
typedef struct ${context}_interface_ctx_s {
|
|
|
|
netsnmp_container *container;
|
|
@ if $m2c_data_cache == 1@
|
|
netsnmp_cache *cache;
|
|
@ end@
|
|
|
|
${context}_registration * user_ctx;
|
|
|
|
netsnmp_table_registration_info tbl_info;
|
|
|
|
netsnmp_baby_steps_access_methods access_multiplexer;
|
|
|
|
@ if $m2c_table_settable@
|
|
u_int table_dirty;
|
|
|
|
@ end@
|
|
} ${context}_interface_ctx;
|
|
|
|
static ${context}_interface_ctx ${context}_if_ctx;
|
|
|
|
static void _${context}_container_init(
|
|
${context}_interface_ctx *if_ctx);
|
|
static void _${context}_container_shutdown(
|
|
${context}_interface_ctx *if_ctx);
|
|
|
|
|
|
netsnmp_container *
|
|
${context}_container_get( void )
|
|
{
|
|
return ${context}_if_ctx.container;
|
|
}
|
|
|
|
${context}_registration *
|
|
${context}_registration_get( void )
|
|
{
|
|
return ${context}_if_ctx.user_ctx;
|
|
}
|
|
|
|
${context}_registration *
|
|
${context}_registration_set( ${context}_registration * newreg )
|
|
{
|
|
${context}_registration * old = ${context}_if_ctx.user_ctx;
|
|
${context}_if_ctx.user_ctx = newreg;
|
|
return old;
|
|
}
|
|
|
|
int
|
|
${context}_container_size( void )
|
|
{
|
|
return CONTAINER_SIZE(${context}_if_ctx.container);
|
|
}
|
|
|
|
@ if $m2c_table_settable@
|
|
u_int
|
|
${context}_dirty_get( void )
|
|
{
|
|
return ${context}_if_ctx.table_dirty;
|
|
}
|
|
|
|
void
|
|
${context}_dirty_set( u_int status )
|
|
{
|
|
DEBUGMSGTL(("${context}:${context}_dirty_set",
|
|
"called. was %d, now %d\n",
|
|
${context}_if_ctx.table_dirty, status));
|
|
${context}_if_ctx.table_dirty = status;
|
|
}
|
|
|
|
@end@
|
|
/*
|
|
* mfd multiplexer modes
|
|
*/
|
|
static Netsnmp_Node_Handler _mfd_${context}_pre_request;
|
|
static Netsnmp_Node_Handler _mfd_${context}_post_request;
|
|
static Netsnmp_Node_Handler _mfd_${context}_object_lookup;
|
|
static Netsnmp_Node_Handler _mfd_${context}_get_values;
|
|
@ if $m2c_table_settable@
|
|
static Netsnmp_Node_Handler _mfd_${context}_check_objects;
|
|
static Netsnmp_Node_Handler _mfd_${context}_undo_setup;
|
|
static Netsnmp_Node_Handler _mfd_${context}_set_values;
|
|
static Netsnmp_Node_Handler _mfd_${context}_undo_cleanup;
|
|
static Netsnmp_Node_Handler _mfd_${context}_undo_values;
|
|
static Netsnmp_Node_Handler _mfd_${context}_commit;
|
|
static Netsnmp_Node_Handler _mfd_${context}_undo_commit;
|
|
static Netsnmp_Node_Handler _mfd_${context}_irreversible_commit;
|
|
@ if $m2c_table_dependencies == 1@
|
|
static Netsnmp_Node_Handler _mfd_${context}_check_dependencies;
|
|
@ end@
|
|
|
|
@ end@ # writable
|
|
@ if ("$m2c_data_context" eq "generated") && (($m2c_undo_embed == 0) || ($m2c_data_allocate == 1))@
|
|
${context}_data *${context}_allocate_data(void);
|
|
|
|
@ end@
|
|
/**
|
|
* @internal
|
|
* Initialize the table $context
|
|
* (Define its contents and how it's structured)
|
|
*/
|
|
void
|
|
_${context}_initialize_interface(${context}_registration * reg_ptr, u_long flags)
|
|
{
|
|
netsnmp_baby_steps_access_methods *access_multiplexer =
|
|
&${context}_if_ctx.access_multiplexer;
|
|
netsnmp_table_registration_info *tbl_info = &${context}_if_ctx.tbl_info;
|
|
netsnmp_handler_registration *reginfo;
|
|
netsnmp_mib_handler *handler;
|
|
int mfd_modes = 0;
|
|
|
|
DEBUGMSGTL(("internal:${context}:_${context}_initialize_interface","called\n"));
|
|
|
|
|
|
/*************************************************
|
|
*
|
|
* save interface context for ${context}
|
|
*/
|
|
/*
|
|
* Setting up the table's definition
|
|
*/
|
|
netsnmp_table_helper_add_indexes(tbl_info,
|
|
@foreach $tabledx index@
|
|
$tabledx.type, /** index: $tabledx */
|
|
@end@
|
|
0);
|
|
|
|
/* Define the minimum and maximum accessible columns. This
|
|
optimizes retrieval. */
|
|
tbl_info->min_column = $context.uc_MIN_COL;
|
|
tbl_info->max_column = $context.uc_MAX_COL;
|
|
|
|
/*
|
|
* save users context
|
|
*/
|
|
${context}_if_ctx.user_ctx = reg_ptr;
|
|
|
|
/*
|
|
* call data access initialization code
|
|
*/
|
|
${context}_init_data(reg_ptr);
|
|
|
|
/*
|
|
* set up the container
|
|
*/
|
|
_${context}_container_init(&${context}_if_ctx);
|
|
if (NULL == ${context}_if_ctx.container) {
|
|
snmp_log(LOG_ERR,"could not initialize container for ${context}\n");
|
|
return;
|
|
}
|
|
|
|
/*
|
|
* access_multiplexer: REQUIRED wrapper for get request handling
|
|
*/
|
|
access_multiplexer->object_lookup = _mfd_${context}_object_lookup;
|
|
access_multiplexer->get_values = _mfd_${context}_get_values;
|
|
|
|
/*
|
|
* no wrappers yet
|
|
*/
|
|
access_multiplexer->pre_request = _mfd_${context}_pre_request;
|
|
access_multiplexer->post_request = _mfd_${context}_post_request;
|
|
|
|
#ifndef NETSNMP_DISABLE_SET_SUPPORT
|
|
##
|
|
@ if $m2c_table_settable@
|
|
|
|
/*
|
|
* REQUIRED wrappers for set request handling
|
|
*/
|
|
access_multiplexer->object_syntax_checks = _mfd_${context}_check_objects;
|
|
access_multiplexer->undo_setup = _mfd_${context}_undo_setup;
|
|
access_multiplexer->undo_cleanup = _mfd_${context}_undo_cleanup;
|
|
access_multiplexer->set_values = _mfd_${context}_set_values;
|
|
access_multiplexer->undo_sets = _mfd_${context}_undo_values;
|
|
|
|
/*
|
|
* no wrappers yet
|
|
*/
|
|
access_multiplexer->commit = _mfd_${context}_commit;
|
|
access_multiplexer->undo_commit = _mfd_${context}_undo_commit;
|
|
access_multiplexer->irreversible_commit = _mfd_${context}_irreversible_commit;
|
|
##
|
|
@ if $m2c_table_dependencies == 1@
|
|
|
|
/*
|
|
* REQUIRED for tables with dependencies
|
|
*/
|
|
access_multiplexer->consistency_checks = _mfd_${context}_check_dependencies;
|
|
@ end@
|
|
@ end@ # writable
|
|
#endif
|
|
|
|
/*************************************************
|
|
*
|
|
* Create a registration, save our reg data, register table.
|
|
*/
|
|
DEBUGMSGTL(("$name:init_$context",
|
|
"Registering $context as a mibs-for-dummies table.\n"));
|
|
handler = netsnmp_baby_steps_access_multiplexer_get(access_multiplexer);
|
|
reginfo = netsnmp_handler_registration_create("${context}", handler,
|
|
${context}_oid,
|
|
${context}_oid_size,
|
|
HANDLER_CAN_BABY_STEP |
|
|
#if (defined(NETSNMP_NO_WRITE_SUPPORT) || defined(NETSNMP_DISABLE_SET_SUPPORT))
|
|
HANDLER_CAN_RONLY
|
|
#else
|
|
@if $m2c_table_settable == 1@
|
|
HANDLER_CAN_RWRITE
|
|
@else@
|
|
HANDLER_CAN_RONLY
|
|
@end@
|
|
#endif /* NETSNMP_NO_WRITE_SUPPORT || NETSNMP_DISABLE_SET_SUPPORT */
|
|
);
|
|
if(NULL == reginfo) {
|
|
snmp_log(LOG_ERR,"error registering table ${context}\n");
|
|
return;
|
|
}
|
|
reginfo->my_reg_void = &${context}_if_ctx;
|
|
|
|
/*************************************************
|
|
*
|
|
* set up baby steps handler, create it and inject it
|
|
*/
|
|
if( access_multiplexer->object_lookup )
|
|
mfd_modes |= BABY_STEP_OBJECT_LOOKUP;
|
|
if( access_multiplexer->pre_request )
|
|
mfd_modes |= BABY_STEP_PRE_REQUEST;
|
|
if( access_multiplexer->post_request )
|
|
mfd_modes |= BABY_STEP_POST_REQUEST;
|
|
|
|
#if !(defined(NETSNMP_NO_WRITE_SUPPORT) || defined(NETSNMP_DISABLE_SET_SUPPORT))
|
|
if( access_multiplexer->set_values )
|
|
mfd_modes |= BABY_STEP_SET_VALUES;
|
|
if( access_multiplexer->irreversible_commit )
|
|
mfd_modes |= BABY_STEP_IRREVERSIBLE_COMMIT;
|
|
if( access_multiplexer->object_syntax_checks )
|
|
mfd_modes |= BABY_STEP_CHECK_OBJECT;
|
|
|
|
if( access_multiplexer->undo_setup )
|
|
mfd_modes |= BABY_STEP_UNDO_SETUP;
|
|
if( access_multiplexer->undo_cleanup )
|
|
mfd_modes |= BABY_STEP_UNDO_CLEANUP;
|
|
if( access_multiplexer->undo_sets )
|
|
mfd_modes |= BABY_STEP_UNDO_SETS;
|
|
|
|
if( access_multiplexer->row_creation )
|
|
mfd_modes |= BABY_STEP_ROW_CREATE;
|
|
if( access_multiplexer->consistency_checks )
|
|
mfd_modes |= BABY_STEP_CHECK_CONSISTENCY;
|
|
if( access_multiplexer->commit )
|
|
mfd_modes |= BABY_STEP_COMMIT;
|
|
if( access_multiplexer->undo_commit )
|
|
mfd_modes |= BABY_STEP_UNDO_COMMIT;
|
|
#endif /* NETSNMP_NO_WRITE_SUPPORT || NETSNMP_DISABLE_SET_SUPPORT */
|
|
|
|
handler = netsnmp_baby_steps_handler_get(mfd_modes);
|
|
netsnmp_inject_handler(reginfo, handler);
|
|
|
|
/*************************************************
|
|
*
|
|
* inject row_merge helper with prefix rootoid_len + 2 (entry.col)
|
|
*/
|
|
handler = netsnmp_get_row_merge_handler(reginfo->rootoid_len + 2);
|
|
netsnmp_inject_handler(reginfo, handler);
|
|
|
|
/*************************************************
|
|
*
|
|
* inject container_table helper
|
|
*/
|
|
handler =
|
|
netsnmp_container_table_handler_get(tbl_info,
|
|
${context}_if_ctx.container,
|
|
TABLE_CONTAINER_KEY_NETSNMP_INDEX);
|
|
netsnmp_inject_handler( reginfo, handler );
|
|
|
|
@ if $m2c_data_cache == 1@
|
|
/*************************************************
|
|
*
|
|
* inject cache helper
|
|
*/
|
|
if(NULL != ${context}_if_ctx.cache) {
|
|
handler = netsnmp_cache_handler_get(${context}_if_ctx.cache);
|
|
netsnmp_inject_handler( reginfo, handler );
|
|
}
|
|
|
|
@ end@
|
|
/*
|
|
* register table
|
|
*/
|
|
netsnmp_register_table(reginfo, tbl_info);
|
|
|
|
@if $m2c_table_persistent == 1@
|
|
/*
|
|
* register config/persistence callbacks
|
|
*/
|
|
${context}_container_init_persistence(${context}_if_ctx.container);
|
|
|
|
@end@
|
|
} /* _${context}_initialize_interface */
|
|
|
|
/**
|
|
* @internal
|
|
* Shutdown the table $context
|
|
*/
|
|
void
|
|
_${context}_shutdown_interface(${context}_registration * reg_ptr)
|
|
{
|
|
/*
|
|
* shutdown the container
|
|
*/
|
|
_${context}_container_shutdown(&${context}_if_ctx);
|
|
}
|
|
|
|
void
|
|
${context}_valid_columns_set(netsnmp_column_info *vc)
|
|
{
|
|
${context}_if_ctx.tbl_info.valid_columns = vc;
|
|
} /* ${context}_valid_columns_set */
|
|
|
|
@include generic-table-indexes-to-oid.m2i@
|
|
@include generic-table-indexes-from-oid.m2i@
|
|
|
|
########################################################################
|
|
##
|
|
@ if (($m2c_data_allocate == 1) || ($m2c_undo_embed == 0)) && ("$m2c_data_context" eq "generated")@
|
|
@ eval $m2c_gda_todo_suppress = 1@ # no todo comments
|
|
@ include generic-data-allocate.m2i@ # resets suppress
|
|
@ end@
|
|
########################################################################
|
|
/* *********************************************************************
|
|
* @internal
|
|
* allocate resources for a ${context}_rowreq_ctx
|
|
*/
|
|
${context}_rowreq_ctx *
|
|
@if $m2c_data_allocate == 1@
|
|
@ eval $m2c_tmp = "${context}_data *data"@
|
|
@ if $m2c_data_init == 1@
|
|
@ eval $m2c_tmp = "$m2c_tmp, void *user_init_ctx"@
|
|
@ end@
|
|
@elsif $m2c_data_init == 1@
|
|
@ eval $m2c_tmp = "void *user_init_ctx"@
|
|
@else@
|
|
@ eval $m2c_tmp = "void"@
|
|
@end@
|
|
${context}_allocate_rowreq_ctx($m2c_tmp)
|
|
{
|
|
${context}_rowreq_ctx *rowreq_ctx =
|
|
SNMP_MALLOC_TYPEDEF(${context}_rowreq_ctx);
|
|
|
|
DEBUGMSGTL(("internal:${context}:${context}_allocate_rowreq_ctx","called\n"));
|
|
|
|
if(NULL == rowreq_ctx) {
|
|
snmp_log(LOG_ERR,"Couldn't allocate memory for a "
|
|
"${context}_rowreq_ctx.\n");
|
|
return NULL;
|
|
}
|
|
@if $m2c_data_allocate == 1@
|
|
else {
|
|
if(NULL != data) {
|
|
/*
|
|
* track if we got data from user
|
|
*/
|
|
rowreq_ctx->rowreq_flags |= MFD_ROW_DATA_FROM_USER;
|
|
rowreq_ctx->data = data;
|
|
}
|
|
else if (NULL == (rowreq_ctx->data = ${context}_allocate_data())) {
|
|
SNMP_FREE(rowreq_ctx);
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* undo context will be allocated when needed (in *_undo_setup)
|
|
*/
|
|
@end@
|
|
|
|
rowreq_ctx->oid_idx.oids = rowreq_ctx->oid_tmp;
|
|
|
|
rowreq_ctx->${context}_data_list = NULL;
|
|
|
|
@if $m2c_data_init == 1@
|
|
/*
|
|
* if we allocated data, call init routine
|
|
*/
|
|
if (!(rowreq_ctx->rowreq_flags & MFD_ROW_DATA_FROM_USER)) {
|
|
if(SNMPERR_SUCCESS !=
|
|
${context}_rowreq_ctx_init(rowreq_ctx, user_init_ctx)) {
|
|
${context}_release_rowreq_ctx(rowreq_ctx);
|
|
rowreq_ctx = NULL;
|
|
}
|
|
}
|
|
@end@
|
|
|
|
return rowreq_ctx;
|
|
} /* ${context}_allocate_rowreq_ctx */
|
|
|
|
/*
|
|
* @internal
|
|
* release resources for a ${context}_rowreq_ctx
|
|
*/
|
|
void
|
|
${context}_release_rowreq_ctx(${context}_rowreq_ctx *rowreq_ctx)
|
|
{
|
|
DEBUGMSGTL(("internal:${context}:${context}_release_rowreq_ctx","called\n"));
|
|
|
|
netsnmp_assert(NULL != rowreq_ctx);
|
|
|
|
@if $m2c_data_init == 1@
|
|
${context}_rowreq_ctx_cleanup(rowreq_ctx);
|
|
@end@
|
|
|
|
@if $m2c_data_allocate == 1@
|
|
/*
|
|
* for non-transient data, don't free data we got from the user
|
|
*/
|
|
if ((rowreq_ctx->data) &&
|
|
!(rowreq_ctx->rowreq_flags & MFD_ROW_DATA_FROM_USER))
|
|
${context}_release_data(rowreq_ctx->data);
|
|
|
|
@end@
|
|
@if $m2c_undo_embed == 0@
|
|
if(rowreq_ctx->undo)
|
|
${context}_release_data(rowreq_ctx->undo);
|
|
|
|
@end@
|
|
/*
|
|
* free index oid pointer
|
|
*/
|
|
if(rowreq_ctx->oid_idx.oids != rowreq_ctx->oid_tmp)
|
|
free(rowreq_ctx->oid_idx.oids);
|
|
|
|
SNMP_FREE(rowreq_ctx);
|
|
} /* ${context}_release_rowreq_ctx */
|
|
|
|
########################################################################
|
|
##
|
|
/**
|
|
* @internal
|
|
* wrapper
|
|
*/
|
|
static int
|
|
_mfd_${context}_pre_request(netsnmp_mib_handler *handler,
|
|
netsnmp_handler_registration *reginfo,
|
|
netsnmp_agent_request_info *agtreq_info,
|
|
netsnmp_request_info *requests)
|
|
{
|
|
int rc;
|
|
|
|
DEBUGMSGTL(("internal:${context}:_mfd_${context}_pre_request",
|
|
"called\n"));
|
|
|
|
if (1 != netsnmp_row_merge_status_first(reginfo, agtreq_info)) {
|
|
DEBUGMSGTL(("internal:${context}",
|
|
"skipping additional pre_request\n"));
|
|
return SNMP_ERR_NOERROR;
|
|
}
|
|
|
|
rc = ${context}_pre_request(${context}_if_ctx.user_ctx);
|
|
if (MFD_SUCCESS != rc) {
|
|
/*
|
|
* nothing we can do about it but log it
|
|
*/
|
|
DEBUGMSGTL(("${context}","error %d from "
|
|
"${context}_pre_request\n", rc));
|
|
netsnmp_request_set_error_all(requests, SNMP_VALIDATE_ERR(rc));
|
|
}
|
|
|
|
return SNMP_ERR_NOERROR;
|
|
} /* _mfd_${context}_pre_request */
|
|
|
|
/**
|
|
* @internal
|
|
* wrapper
|
|
*/
|
|
static int
|
|
_mfd_${context}_post_request(netsnmp_mib_handler *handler,
|
|
netsnmp_handler_registration *reginfo,
|
|
netsnmp_agent_request_info *agtreq_info,
|
|
netsnmp_request_info *requests)
|
|
{
|
|
${context}_rowreq_ctx *rowreq_ctx = (${context}_rowreq_ctx*)
|
|
netsnmp_container_table_row_extract(requests);
|
|
int rc, packet_rc;
|
|
|
|
DEBUGMSGTL(("internal:${context}:_mfd_${context}_post_request",
|
|
"called\n"));
|
|
|
|
/*
|
|
* release row context, if deleted
|
|
*/
|
|
if (rowreq_ctx && (rowreq_ctx->rowreq_flags & MFD_ROW_DELETED))
|
|
${context}_release_rowreq_ctx(rowreq_ctx);
|
|
|
|
/*
|
|
* wait for last call before calling user
|
|
*/
|
|
if (1 != netsnmp_row_merge_status_last(reginfo, agtreq_info)) {
|
|
DEBUGMSGTL(("internal:${context}",
|
|
"waiting for last post_request\n"));
|
|
return SNMP_ERR_NOERROR;
|
|
}
|
|
|
|
packet_rc = netsnmp_check_all_requests_error(agtreq_info->asp, 0);
|
|
@ if $m2c_table_settable@
|
|
if ((MFD_SUCCESS != packet_rc) && ${context}_dirty_get()) {
|
|
/*
|
|
* we shouldn't get here. the undo steps should also clear
|
|
* the dirty flags.
|
|
*/
|
|
snmp_log(LOG_WARNING, "${context} dirty flag set in post_request "
|
|
"but status != SUCCESS.\n");
|
|
}
|
|
|
|
@ end@
|
|
rc = ${context}_post_request(${context}_if_ctx.user_ctx,packet_rc);
|
|
if (MFD_SUCCESS != rc) {
|
|
/*
|
|
* nothing we can do about it but log it
|
|
*/
|
|
DEBUGMSGTL(("${context}","error %d from "
|
|
"${context}_post_request\n", rc));
|
|
}
|
|
|
|
return SNMP_ERR_NOERROR;
|
|
} /* _mfd_${context}_post_request */
|
|
|
|
########################################################################
|
|
##
|
|
@if ($m2c_table_row_creation == 1) || ($m2c_table_persistent == 1)@
|
|
NETSNMP_STATIC_INLINE int
|
|
_${context}_check_indexes(${context}_rowreq_ctx * rowreq_ctx)
|
|
{
|
|
int rc = SNMPERR_SUCCESS;
|
|
|
|
DEBUGMSGTL(("internal:${context}:_${context}_check_indexes","called\n"));
|
|
|
|
netsnmp_assert(NULL != rowreq_ctx);
|
|
|
|
##
|
|
@if $m2c_table_external_indexes != 0@
|
|
/*
|
|
* check that the corresponding EXTERNAL row exists
|
|
*/
|
|
@ foreach $node externalindex@
|
|
@ include m2c_setup_node.m2i@
|
|
|
|
/* (INDEX) $m2c_node_summary */
|
|
rc = ${context}_${node}_check_index( rowreq_ctx );
|
|
if(MFD_SUCCESS != rc)
|
|
return SNMP_ERR_NOCREATION;
|
|
@ end@ # for each nonindex
|
|
|
|
@end@ # external index
|
|
@ foreach $node internalindex@
|
|
@ include m2c_setup_node.m2i@
|
|
|
|
/* (INDEX) $m2c_node_summary */
|
|
@ eval $m2c_nv_val = "rowreq_ctx->tbl_idx.$node"@
|
|
@ eval $m2c_nv_len = "rowreq_ctx->tbl_idx.${node}_len"@
|
|
@ eval $m2c_nv_str = "rowreq_ctx->tbl_idx.$node"@
|
|
@ include node-validate.m2i@
|
|
if (MFD_SUCCESS != rc)
|
|
return rc;
|
|
rc = ${node}_check_index( rowreq_ctx );
|
|
if(MFD_SUCCESS != rc)
|
|
return SNMP_ERR_NOCREATION;
|
|
@ end@ # for each internalindex
|
|
|
|
/*
|
|
* if individual parts look ok, check them as a whole
|
|
*/
|
|
return ${context}_validate_index( ${context}_if_ctx.user_ctx, rowreq_ctx );
|
|
} /* _${context}_check_indexes */
|
|
##----------------------------------------------------------------------
|
|
/**
|
|
* @internal
|
|
* wrapper
|
|
*/
|
|
static ${table}_rowreq_ctx *
|
|
_mfd_${context}_rowreq_from_index(netsnmp_index *oid_idx, int * rc_ptr)
|
|
{
|
|
${context}_rowreq_ctx * rowreq_ctx;
|
|
${context}_mib_index mib_idx;
|
|
int rc;
|
|
|
|
DEBUGMSGTL(("internal:${context}:_mfd_${context}_rowreq_from_index",
|
|
"called\n"));
|
|
|
|
if (NULL == rc_ptr)
|
|
rc_ptr = &rc;
|
|
*rc_ptr = MFD_SUCCESS;
|
|
|
|
memset(&mib_idx, 0x0, sizeof(mib_idx));
|
|
|
|
/*
|
|
* try to parse oid
|
|
*/
|
|
*rc_ptr = ${context}_index_from_oid(oid_idx, &mib_idx);
|
|
if(MFD_SUCCESS != *rc_ptr) {
|
|
DEBUGMSGT(("$context", "error parsing index\n"));
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* allocate new context
|
|
*/
|
|
@ eval $m2c_tmp = ""@
|
|
@ if ($m2c_data_allocate == 1) || ($m2c_data_init == 1)@
|
|
@ eval $m2c_tmp = "NULL"@
|
|
@ if ($m2c_data_allocate == 1) && ($m2c_data_init == 1)@
|
|
@ eval $m2c_tmp = "$m2c_tmp, NULL"@
|
|
@ @end@
|
|
@ end@
|
|
rowreq_ctx = ${context}_allocate_rowreq_ctx($m2c_tmp);
|
|
if (NULL == rowreq_ctx) {
|
|
*rc_ptr = MFD_ERROR;
|
|
return NULL; /* msg already logged */
|
|
}
|
|
|
|
memcpy(&rowreq_ctx->tbl_idx, &mib_idx, sizeof(mib_idx));
|
|
|
|
/*
|
|
* check indexes
|
|
*/
|
|
*rc_ptr = _${context}_check_indexes(rowreq_ctx);
|
|
if(MFD_SUCCESS != *rc_ptr) {
|
|
netsnmp_assert((*rc_ptr == SNMP_ERR_NOCREATION) ||
|
|
(*rc_ptr == SNMP_ERR_INCONSISTENTNAME));
|
|
${context}_release_rowreq_ctx(rowreq_ctx);
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* copy indexes
|
|
*/
|
|
rowreq_ctx->oid_idx.len = oid_idx->len;
|
|
memcpy(rowreq_ctx->oid_idx.oids, oid_idx->oids, oid_idx->len * sizeof(oid));
|
|
|
|
return rowreq_ctx;
|
|
} /* _mfd_${context}_rowreq_from_index */
|
|
|
|
|
|
@end@ # row creation
|
|
/**
|
|
* @internal
|
|
* wrapper
|
|
*/
|
|
static int
|
|
_mfd_${context}_object_lookup(netsnmp_mib_handler *handler,
|
|
netsnmp_handler_registration *reginfo,
|
|
netsnmp_agent_request_info *agtreq_info,
|
|
netsnmp_request_info *requests)
|
|
{
|
|
int rc = SNMP_ERR_NOERROR;
|
|
${context}_rowreq_ctx *rowreq_ctx = (${context}_rowreq_ctx*)
|
|
netsnmp_container_table_row_extract(requests);
|
|
|
|
DEBUGMSGTL(("internal:${context}:_mfd_${context}_object_lookup","called\n"));
|
|
|
|
/*
|
|
* get our context from mfd
|
|
* ${context}_interface_ctx *if_ctx =
|
|
* (${context}_interface_ctx *)reginfo->my_reg_void;
|
|
*/
|
|
|
|
if(NULL == rowreq_ctx) {
|
|
@ if $m2c_table_row_creation == 0@
|
|
rc = SNMP_ERR_NOCREATION;
|
|
@ else@
|
|
netsnmp_table_request_info *tblreq_info;
|
|
netsnmp_index oid_idx;
|
|
|
|
tblreq_info = netsnmp_extract_table_info(requests);
|
|
if(NULL == tblreq_info) {
|
|
snmp_log(LOG_ERR, "request had no table info\n");
|
|
return MFD_ERROR;
|
|
}
|
|
|
|
/*
|
|
* try create rowreq
|
|
*/
|
|
oid_idx.oids = tblreq_info->index_oid;
|
|
oid_idx.len = tblreq_info->index_oid_len;
|
|
|
|
rowreq_ctx = _mfd_${context}_rowreq_from_index(&oid_idx, &rc);
|
|
if(MFD_SUCCESS == rc) {
|
|
netsnmp_assert(NULL != rowreq_ctx);
|
|
rowreq_ctx->rowreq_flags |= MFD_ROW_CREATED;
|
|
/*
|
|
* add rowreq_ctx to request data lists
|
|
*/
|
|
netsnmp_container_table_row_insert(requests, (netsnmp_index*)rowreq_ctx);
|
|
}
|
|
@ end@ // row creation
|
|
}
|
|
|
|
if (MFD_SUCCESS != rc)
|
|
netsnmp_request_set_error_all(requests, rc);
|
|
else
|
|
${context}_row_prep(rowreq_ctx);
|
|
|
|
return SNMP_VALIDATE_ERR(rc);
|
|
} /* _mfd_${context}_object_lookup */
|
|
|
|
########################################################################
|
|
##
|
|
/***********************************************************************
|
|
*
|
|
* GET processing
|
|
*
|
|
***********************************************************************/
|
|
/*
|
|
* @internal
|
|
* Retrieve the value for a particular column
|
|
*/
|
|
NETSNMP_STATIC_INLINE int
|
|
_${context}_get_column( ${context}_rowreq_ctx *rowreq_ctx,
|
|
netsnmp_variable_list *var, int column )
|
|
{
|
|
int rc = SNMPERR_SUCCESS;
|
|
|
|
DEBUGMSGTL(("internal:${context}:_mfd_${context}_get_column",
|
|
"called for %d\n", column));
|
|
|
|
|
|
netsnmp_assert(NULL != rowreq_ctx);
|
|
|
|
switch(column) {
|
|
@ foreach $node internalindex@
|
|
@ include m2c_setup_node.m2i@
|
|
@ if $node.accessible == 1@
|
|
|
|
/* (INDEX) $m2c_node_summary */
|
|
case COLUMN_$node.uc:
|
|
var->type = $node.type;
|
|
@ if $m2c_node_needlength == 1@
|
|
/*
|
|
* NOTE: val_len is in bytes, ${node}_len might not be (e.g. oids)
|
|
*/
|
|
if (var->val_len < (rowreq_ctx->tbl_idx.${node}_len *
|
|
sizeof(rowreq_ctx->tbl_idx.${node}[0]))) {
|
|
var->val.string = malloc(rowreq_ctx->tbl_idx.${node}_len *
|
|
sizeof(rowreq_ctx->tbl_idx.${node}[0]));
|
|
}
|
|
var->val_len = rowreq_ctx->tbl_idx.${node}_len * sizeof(rowreq_ctx->tbl_idx.${node}[0]);
|
|
memcpy( var->val.string, rowreq_ctx->tbl_idx.$node, var->val_len );
|
|
@ else@
|
|
var->val_len = sizeof($m2c_decl);
|
|
(*var->val.integer) = rowreq_ctx->tbl_idx.$node;
|
|
@ end@
|
|
break;
|
|
@ end@ ## accessible
|
|
@ end@ ## index
|
|
@ foreach $node nonindex@
|
|
@ include m2c_setup_node.m2i@
|
|
@ if $node.accessible == 1@
|
|
|
|
/* $m2c_node_summary */
|
|
case COLUMN_$node.uc:
|
|
@ if $m2c_table_sparse == 1@
|
|
if (! (COLUMN_$node.uc_FLAG & rowreq_ctx->column_exists_flags)) {
|
|
DEBUGMSGTL(("internal:${context}:_mfd_${context}_get_column",
|
|
"column %d ($node) doesn't exist\n", column));
|
|
return MFD_SKIP;
|
|
}
|
|
|
|
@ end@
|
|
## use sizeof except for BITS
|
|
@ if $m2c_node_needlength == 0@
|
|
@ if "$node.perltype" eq "BITS"@
|
|
{
|
|
$m2c_decl mask = 0xff << ((sizeof($m2c_decl) - 1) * 8);
|
|
int idx = 0;
|
|
@ else@
|
|
var->val_len = sizeof($m2c_decl);
|
|
@ end@
|
|
@ end@
|
|
var->type = $node.type;
|
|
rc = ${node}_get(rowreq_ctx, $m2c_node_var_ref );
|
|
@ if ($m2c_node_needlength == 0) && ("$node.perltype" eq "BITS")@
|
|
/*
|
|
* check for length of bits string
|
|
*/
|
|
var->val_len = 0;
|
|
while( 0 != mask ) {
|
|
++idx;
|
|
if ( ntohl( *(($m2c_decl *) var->val.string) ) & mask )
|
|
var->val_len = idx;
|
|
mask = mask >> 8;
|
|
}
|
|
}
|
|
@ end@
|
|
break;
|
|
@ end@ # accessible
|
|
@ end@ # for each column
|
|
|
|
default:
|
|
if ($context.uc_MIN_COL <= column && column <= $context.uc_MAX_COL) {
|
|
DEBUGMSGTL(("internal:${context}:_mfd_${context}_get_column",
|
|
"assume column %d is reserved\n", column));
|
|
rc = MFD_SKIP;
|
|
} else {
|
|
snmp_log(LOG_ERR,
|
|
"unknown column %d in _${context}_get_column\n", column);
|
|
}
|
|
break;
|
|
}
|
|
|
|
return rc;
|
|
} /* _${context}_get_column */
|
|
|
|
########################################################################
|
|
##
|
|
int
|
|
_mfd_${context}_get_values(netsnmp_mib_handler *handler,
|
|
netsnmp_handler_registration *reginfo,
|
|
netsnmp_agent_request_info *agtreq_info,
|
|
netsnmp_request_info *requests)
|
|
{
|
|
${context}_rowreq_ctx *rowreq_ctx = (${context}_rowreq_ctx*)
|
|
netsnmp_container_table_row_extract(requests);
|
|
netsnmp_table_request_info * tri;
|
|
u_char * old_string;
|
|
void (*dataFreeHook)(void *);
|
|
int rc;
|
|
|
|
DEBUGMSGTL(("internal:${context}:_mfd_${context}_get_values","called\n"));
|
|
|
|
netsnmp_assert(NULL != rowreq_ctx);
|
|
|
|
@if $m2c_table_sparse == 1@
|
|
DEBUGMSGTL(("9:${context}:_mfd_${context}_get_values",
|
|
"exists %x\n", rowreq_ctx->column_exists_flags));
|
|
|
|
@end@
|
|
for(;requests; requests = requests->next) {
|
|
/*
|
|
* save old pointer, so we can free it if replaced
|
|
*/
|
|
old_string = requests->requestvb->val.string;
|
|
dataFreeHook = requests->requestvb->dataFreeHook;
|
|
if(NULL == requests->requestvb->val.string) {
|
|
requests->requestvb->val.string = requests->requestvb->buf;
|
|
requests->requestvb->val_len = sizeof(requests->requestvb->buf);
|
|
}
|
|
else if(requests->requestvb->buf == requests->requestvb->val.string) {
|
|
if(requests->requestvb->val_len != sizeof(requests->requestvb->buf))
|
|
requests->requestvb->val_len = sizeof(requests->requestvb->buf);
|
|
}
|
|
|
|
/*
|
|
* get column data
|
|
*/
|
|
tri = netsnmp_extract_table_info(requests);
|
|
if(NULL == tri)
|
|
continue;
|
|
|
|
rc = _${context}_get_column(rowreq_ctx, requests->requestvb, tri->colnum);
|
|
if(rc) {
|
|
if(MFD_SKIP == rc) {
|
|
requests->requestvb->type = SNMP_NOSUCHINSTANCE;
|
|
rc = SNMP_ERR_NOERROR;
|
|
}
|
|
}
|
|
else if (NULL == requests->requestvb->val.string) {
|
|
snmp_log(LOG_ERR,"NULL varbind data pointer!\n");
|
|
rc = SNMP_ERR_GENERR;
|
|
}
|
|
if(rc)
|
|
netsnmp_request_set_error(requests, SNMP_VALIDATE_ERR(rc));
|
|
|
|
/*
|
|
* if the buffer wasn't used previously for the old data (i.e. it
|
|
* was allcoated memory) and the get routine replaced the pointer,
|
|
* we need to free the previous pointer.
|
|
*/
|
|
if(old_string && (old_string != requests->requestvb->buf) &&
|
|
(requests->requestvb->val.string != old_string)) {
|
|
if(dataFreeHook)
|
|
(*dataFreeHook)(old_string);
|
|
else
|
|
free(old_string);
|
|
}
|
|
} /* for results */
|
|
|
|
return SNMP_ERR_NOERROR;
|
|
} /* _mfd_${context}_get_values */
|
|
|
|
########################################################################
|
|
##
|
|
/***********************************************************************
|
|
*
|
|
* SET processing
|
|
*
|
|
***********************************************************************/
|
|
|
|
@if $m2c_table_settable == 0@
|
|
/*
|
|
* SET PROCESSING NOT APPLICABLE (per MIB or user setting)
|
|
*/
|
|
@else@
|
|
/*----------------------------------------------------------------------
|
|
*
|
|
* SET: Syntax checks
|
|
*
|
|
*---------------------------------------------------------------------*/
|
|
/*
|
|
* @internal
|
|
* Check the syntax for a particular column
|
|
*/
|
|
NETSNMP_STATIC_INLINE int
|
|
_${context}_check_column( ${context}_rowreq_ctx *rowreq_ctx,
|
|
netsnmp_variable_list *var, int column )
|
|
{
|
|
int rc = SNMPERR_SUCCESS;
|
|
|
|
DEBUGMSGTL(("internal:${context}:_${context}_check_column",
|
|
"called for %d\n", column));
|
|
|
|
netsnmp_assert(NULL != rowreq_ctx);
|
|
|
|
switch(column) {
|
|
@ eval $m2c_nvv_item = "${m2c_context_item}tbl_idx."@
|
|
@ foreach $node internalindex@
|
|
@ include m2c_setup_node.m2i@
|
|
/* (INDEX) $m2c_node_summary */
|
|
case COLUMN_$node.uc:
|
|
rc = SNMP_ERR_NOTWRITABLE; /* can not change index of active row */
|
|
break;
|
|
@ end@ ## index
|
|
@ eval $m2c_nvv_item = "$m2c_data_item"@
|
|
@ foreach $node nonindex@
|
|
@ include m2c_setup_node.m2i@
|
|
@ if $node.settable == 0@
|
|
|
|
/* $m2c_node_summary */
|
|
case COLUMN_$node.uc:
|
|
rc = SNMP_ERR_NOTWRITABLE;
|
|
break;
|
|
@ next@
|
|
@ end@
|
|
|
|
/* $m2c_node_summary */
|
|
case COLUMN_$node.uc:
|
|
@ include node-varbind-validate.m2i@
|
|
if(SNMPERR_SUCCESS != rc) {
|
|
DEBUGMSGTL(("${context}:_${context}_check_column:$node",
|
|
"varbind validation failed (eg bad type or size)\n"));
|
|
}
|
|
else {
|
|
rc = ${node}_check_value( rowreq_ctx, $m2c_node_var_val );
|
|
if((MFD_SUCCESS != rc) && (MFD_NOT_VALID_EVER != rc) &&
|
|
(MFD_NOT_VALID_NOW != rc)) {
|
|
snmp_log(LOG_ERR, "bad rc %d from ${node}_check_value\n", rc);
|
|
rc = SNMP_ERR_GENERR;
|
|
}
|
|
}
|
|
break;
|
|
@ end@ # for each nonindex
|
|
|
|
default: /** We shouldn't get here */
|
|
rc = SNMP_ERR_GENERR;
|
|
snmp_log(LOG_ERR, "unknown column %d in _${context}_check_column\n", column);
|
|
}
|
|
|
|
return rc;
|
|
} /* _${context}_check_column */
|
|
|
|
##----------------------------------------------------------------------
|
|
int
|
|
_mfd_${context}_check_objects(netsnmp_mib_handler *handler,
|
|
netsnmp_handler_registration *reginfo,
|
|
netsnmp_agent_request_info *agtreq_info,
|
|
netsnmp_request_info *requests)
|
|
{
|
|
${context}_rowreq_ctx *rowreq_ctx = (${context}_rowreq_ctx*)
|
|
netsnmp_container_table_row_extract(requests);
|
|
netsnmp_table_request_info * tri;
|
|
int rc;
|
|
|
|
DEBUGMSGTL(("internal:${context}:_mfd_${context}_check_objects","called\n"));
|
|
|
|
netsnmp_assert(NULL != rowreq_ctx);
|
|
|
|
for(;requests; requests = requests->next) {
|
|
|
|
/*
|
|
* get column number from table request info, and check that column
|
|
*/
|
|
tri = netsnmp_extract_table_info(requests);
|
|
if(NULL == tri)
|
|
continue;
|
|
|
|
rc = _${context}_check_column(rowreq_ctx, requests->requestvb, tri->colnum);
|
|
if(rc) {
|
|
netsnmp_request_set_error(requests, SNMP_VALIDATE_ERR(rc));
|
|
break;
|
|
}
|
|
|
|
} /* for results */
|
|
|
|
return SNMP_ERR_NOERROR;
|
|
} /* _mfd_${context}_check_objects */
|
|
|
|
|
|
@ if $m2c_table_dependencies == 1@
|
|
/*----------------------------------------------------------------------
|
|
*
|
|
* SET: check dependencies
|
|
*
|
|
*---------------------------------------------------------------------*/
|
|
/*
|
|
* @internal
|
|
* Check dependencies wrapper
|
|
*/
|
|
static int
|
|
_mfd_${context}_check_dependencies(netsnmp_mib_handler *handler,
|
|
netsnmp_handler_registration *reginfo,
|
|
netsnmp_agent_request_info *agtreq_info,
|
|
netsnmp_request_info *requests)
|
|
{
|
|
int rc;
|
|
${context}_rowreq_ctx *rowreq_ctx = (${context}_rowreq_ctx*)
|
|
netsnmp_container_table_row_extract(requests);
|
|
DEBUGMSGTL(("internal:${context}:_mfd_${context}_check_dependencies","called\n"));
|
|
|
|
netsnmp_assert(NULL != rowreq_ctx);
|
|
|
|
rc = ${context}_check_dependencies(rowreq_ctx);
|
|
if(rc){
|
|
DEBUGMSGTL(("${context}:mfd","error %d from "
|
|
"${context}_check_dependencies\n", rc));
|
|
netsnmp_request_set_error_all(requests, SNMP_VALIDATE_ERR(rc));
|
|
}
|
|
|
|
return SNMP_ERR_NOERROR;
|
|
} /* _mfd_${context}_check_dependencies */
|
|
|
|
@end@ // dependencies
|
|
/*----------------------------------------------------------------------
|
|
*
|
|
* SET: Undo setup
|
|
*
|
|
*---------------------------------------------------------------------*/
|
|
/*
|
|
* @internal
|
|
* Set the value for a particular column
|
|
*/
|
|
NETSNMP_STATIC_INLINE int
|
|
_${context}_undo_setup_column( ${context}_rowreq_ctx *rowreq_ctx, int column )
|
|
{
|
|
int rc = SNMPERR_SUCCESS;
|
|
|
|
DEBUGMSGTL(("internal:${context}:_${context}_undo_setup_column",
|
|
"called for %d\n", column));
|
|
|
|
netsnmp_assert(NULL != rowreq_ctx);
|
|
|
|
switch(column) {
|
|
@ foreach $node nonindex@
|
|
@ include m2c_setup_node.m2i@
|
|
@ if $node.settable == 1@
|
|
|
|
/* $m2c_node_summary */
|
|
case COLUMN_$node.uc:
|
|
rowreq_ctx->column_set_flags |= COLUMN_$node.uc_FLAG;
|
|
rc = ${node}_undo_setup(rowreq_ctx );
|
|
break;
|
|
@ end@ # settable
|
|
@ end@ # for each column
|
|
|
|
default:
|
|
snmp_log(LOG_ERR,"unknown column %d in _${context}_undo_setup_column\n", column);
|
|
break;
|
|
}
|
|
|
|
return rc;
|
|
} /* _${context}_undo_setup_column */
|
|
|
|
|
|
##----------------------------------------------------------------------
|
|
/**
|
|
* @internal
|
|
* undo setup
|
|
*/
|
|
int
|
|
_mfd_${context}_undo_setup(netsnmp_mib_handler *handler,
|
|
netsnmp_handler_registration *reginfo,
|
|
netsnmp_agent_request_info *agtreq_info,
|
|
netsnmp_request_info *requests)
|
|
{
|
|
int rc;
|
|
${context}_rowreq_ctx *rowreq_ctx = (${context}_rowreq_ctx*)
|
|
netsnmp_container_table_row_extract(requests);
|
|
|
|
DEBUGMSGTL(("internal:${context}:_mfd_${context}_undo_setup","called\n"));
|
|
|
|
netsnmp_assert(NULL != rowreq_ctx);
|
|
|
|
@if $m2c_undo_embed == 0@
|
|
/*
|
|
* allocate undo context
|
|
*/
|
|
rowreq_ctx->undo = ${context}_allocate_data();
|
|
if(NULL == rowreq_ctx->undo) {
|
|
/** msg already logged */
|
|
netsnmp_request_set_error_all(requests, SNMP_ERR_RESOURCEUNAVAILABLE);
|
|
return SNMP_ERR_NOERROR;
|
|
}
|
|
|
|
@end@
|
|
/*
|
|
* row undo setup
|
|
*/
|
|
rowreq_ctx->column_set_flags = 0;
|
|
rc = ${context}_undo_setup(rowreq_ctx);
|
|
if (MFD_SUCCESS != rc) {
|
|
DEBUGMSGTL(("${context}:mfd","error %d from "
|
|
"${context}_undo_setup\n", rc));
|
|
netsnmp_request_set_error_all(requests, SNMP_VALIDATE_ERR(rc));
|
|
}
|
|
else {
|
|
/*
|
|
* column undo setup
|
|
*/
|
|
netsnmp_table_request_info * tri;
|
|
for(;requests; requests = requests->next) {
|
|
/*
|
|
* set column data
|
|
*/
|
|
tri = netsnmp_extract_table_info(requests);
|
|
if(NULL == tri)
|
|
continue;
|
|
|
|
rc = _${context}_undo_setup_column(rowreq_ctx, tri->colnum);
|
|
if(MFD_SUCCESS != rc) {
|
|
DEBUGMSGTL(("${context}:mfd","error %d from "
|
|
"${context}_undo_setup_column\n", rc));
|
|
netsnmp_set_request_error(agtreq_info, requests, SNMP_VALIDATE_ERR(rc));
|
|
}
|
|
} /* for results */
|
|
}
|
|
|
|
return SNMP_ERR_NOERROR;
|
|
} /* _mfd_${context}_undo_setup */
|
|
|
|
/**
|
|
* @internal
|
|
* undo setup
|
|
*/
|
|
int
|
|
_mfd_${context}_undo_cleanup(netsnmp_mib_handler *handler,
|
|
netsnmp_handler_registration *reginfo,
|
|
netsnmp_agent_request_info *agtreq_info,
|
|
netsnmp_request_info *requests)
|
|
{
|
|
${context}_rowreq_ctx *rowreq_ctx = (${context}_rowreq_ctx*)
|
|
netsnmp_container_table_row_extract(requests);
|
|
int rc;
|
|
|
|
DEBUGMSGTL(("internal:${context}:_mfd_${context}_undo_cleanup","called\n"));
|
|
|
|
/*
|
|
* failed row create in early stages has no rowreq_ctx
|
|
*/
|
|
if (NULL == rowreq_ctx)
|
|
return MFD_SUCCESS;
|
|
|
|
/*
|
|
* call user cleanup
|
|
*/
|
|
rc = ${context}_undo_cleanup(rowreq_ctx);
|
|
if (MFD_SUCCESS != rc) {
|
|
/*
|
|
* nothing we can do about it but log it
|
|
*/
|
|
DEBUGMSGTL(("${context}:mfd","error %d from "
|
|
"${context}_undo_cleanup\n", rc));
|
|
}
|
|
|
|
@if $m2c_undo_embed == 0@
|
|
/*
|
|
* release undo context, if needed
|
|
*/
|
|
if(rowreq_ctx->undo) {
|
|
${context}_release_data(rowreq_ctx->undo);
|
|
rowreq_ctx->undo = NULL;
|
|
}
|
|
|
|
@end@
|
|
|
|
return SNMP_ERR_NOERROR;
|
|
} /* _mfd_${context}_undo_cleanup */
|
|
|
|
/*----------------------------------------------------------------------
|
|
*
|
|
* SET: Set values
|
|
*
|
|
*---------------------------------------------------------------------*/
|
|
/*
|
|
* @internal
|
|
* Set the value for a particular column
|
|
*/
|
|
NETSNMP_STATIC_INLINE int
|
|
_${context}_set_column( ${context}_rowreq_ctx *rowreq_ctx,
|
|
netsnmp_variable_list *var, int column )
|
|
{
|
|
int rc = SNMPERR_SUCCESS;
|
|
|
|
DEBUGMSGTL(("internal:${context}:_${context}_set_column",
|
|
"called for %d\n", column));
|
|
|
|
netsnmp_assert(NULL != rowreq_ctx);
|
|
|
|
switch(column) {
|
|
@ foreach $node nonindex@
|
|
@ include m2c_setup_node.m2i@
|
|
@ if $node.settable == 1@
|
|
|
|
/* $m2c_node_summary */
|
|
case COLUMN_$node.uc:
|
|
rowreq_ctx->column_set_flags |= COLUMN_$node.uc_FLAG;
|
|
rc = ${node}_set(rowreq_ctx, $m2c_node_var_val );
|
|
break;
|
|
@ end@ # settable
|
|
@ end@ # for each column
|
|
|
|
default:
|
|
snmp_log(LOG_ERR,"unknown column %d in _${context}_set_column\n", column);
|
|
rc = SNMP_ERR_GENERR;
|
|
break;
|
|
}
|
|
|
|
return rc;
|
|
} /* _${context}_set_column */
|
|
|
|
########################################################################
|
|
##
|
|
int
|
|
_mfd_${context}_set_values(netsnmp_mib_handler *handler,
|
|
netsnmp_handler_registration *reginfo,
|
|
netsnmp_agent_request_info *agtreq_info,
|
|
netsnmp_request_info *requests)
|
|
{
|
|
${context}_rowreq_ctx *rowreq_ctx = (${context}_rowreq_ctx*)
|
|
netsnmp_container_table_row_extract(requests);
|
|
netsnmp_table_request_info * tri;
|
|
int rc = SNMP_ERR_NOERROR;
|
|
|
|
DEBUGMSGTL(("internal:${context}:_mfd_${context}_set_values","called\n"));
|
|
|
|
netsnmp_assert(NULL != rowreq_ctx);
|
|
|
|
rowreq_ctx->column_set_flags = 0;
|
|
for(;requests; requests = requests->next) {
|
|
/*
|
|
* set column data
|
|
*/
|
|
tri = netsnmp_extract_table_info(requests);
|
|
if(NULL == tri)
|
|
continue;
|
|
|
|
rc = _${context}_set_column(rowreq_ctx,
|
|
requests->requestvb, tri->colnum);
|
|
if(MFD_SUCCESS != rc) {
|
|
DEBUGMSGTL(("${context}:mfd","error %d from "
|
|
"${context}_set_column\n", rc));
|
|
netsnmp_set_request_error(agtreq_info, requests, SNMP_VALIDATE_ERR(rc));
|
|
}
|
|
} /* for results */
|
|
|
|
return SNMP_ERR_NOERROR;
|
|
} /* _mfd_${context}_set_values */
|
|
|
|
/*----------------------------------------------------------------------
|
|
*
|
|
* SET: commit
|
|
*
|
|
*---------------------------------------------------------------------*/
|
|
/**
|
|
* @internal
|
|
* commit the values
|
|
*/
|
|
int
|
|
_mfd_${context}_commit(netsnmp_mib_handler *handler,
|
|
netsnmp_handler_registration *reginfo,
|
|
netsnmp_agent_request_info *agtreq_info,
|
|
netsnmp_request_info *requests)
|
|
{
|
|
int rc;
|
|
${context}_rowreq_ctx *rowreq_ctx = (${context}_rowreq_ctx*)
|
|
netsnmp_container_table_row_extract(requests);
|
|
|
|
DEBUGMSGTL(("internal:${context}:_mfd_${context}_commit","called\n"));
|
|
|
|
netsnmp_assert(NULL != rowreq_ctx);
|
|
|
|
rc = ${context}_commit(rowreq_ctx);
|
|
if (MFD_SUCCESS != rc) {
|
|
DEBUGMSGTL(("${context}:mfd","error %d from "
|
|
"${context}_commit\n", rc));
|
|
netsnmp_request_set_error_all(requests, SNMP_VALIDATE_ERR(rc));
|
|
}
|
|
|
|
if (rowreq_ctx->rowreq_flags & MFD_ROW_DIRTY) {
|
|
/*
|
|
* if we successfully commited this row, set the dirty flag. Use the
|
|
* current value + 1 (i.e. dirty = # rows changed).
|
|
* this is checked in post_request...
|
|
*/
|
|
${context}_dirty_set( ${context}_dirty_get() + 1 ); /* set table dirty flag */
|
|
}
|
|
|
|
return SNMP_ERR_NOERROR;
|
|
}
|
|
|
|
int
|
|
_mfd_${context}_undo_commit(netsnmp_mib_handler *handler,
|
|
netsnmp_handler_registration *reginfo,
|
|
netsnmp_agent_request_info *agtreq_info,
|
|
netsnmp_request_info *requests)
|
|
{
|
|
int rc;
|
|
${context}_rowreq_ctx *rowreq_ctx = (${context}_rowreq_ctx*)
|
|
netsnmp_container_table_row_extract(requests);
|
|
|
|
DEBUGMSGTL(("internal:${context}:_mfd_${context}_undo_commit","called\n"));
|
|
|
|
netsnmp_assert(NULL != rowreq_ctx);
|
|
|
|
if (rowreq_ctx->rowreq_flags & MFD_ROW_DIRTY) {
|
|
u_int d = ${context}_dirty_get();
|
|
|
|
netsnmp_assert(d != 0);
|
|
if(d)
|
|
${context}_dirty_set( d - 1 );
|
|
}
|
|
|
|
rc = ${context}_undo_commit(rowreq_ctx);
|
|
if (MFD_SUCCESS != rc) {
|
|
/*
|
|
* nothing we can do about it but log it
|
|
*/
|
|
DEBUGMSGTL(("${context}:mfd","error %d from "
|
|
"${context}_undo_commit\n", rc));
|
|
}
|
|
|
|
if (rowreq_ctx->rowreq_flags & MFD_ROW_DIRTY) {
|
|
snmp_log(LOG_WARNING, "${context} row dirty flag still set after undo_commit\n");
|
|
rowreq_ctx->rowreq_flags &= ~MFD_ROW_DIRTY;
|
|
}
|
|
|
|
return SNMP_ERR_NOERROR;
|
|
} /* _mfd_${context}_commit */
|
|
|
|
/*----------------------------------------------------------------------
|
|
*
|
|
* SET: Undo
|
|
*
|
|
*---------------------------------------------------------------------*/
|
|
/**
|
|
* @internal
|
|
* undo the value for a particular column
|
|
*/
|
|
NETSNMP_STATIC_INLINE int
|
|
_${context}_undo_column( ${context}_rowreq_ctx *rowreq_ctx,
|
|
netsnmp_variable_list *var, int column )
|
|
{
|
|
int rc = SNMPERR_SUCCESS;
|
|
|
|
DEBUGMSGTL(("internal:${context}:_${context}_undo_column",
|
|
"called for %d\n", column));
|
|
|
|
netsnmp_assert(NULL != rowreq_ctx);
|
|
|
|
switch(column) {
|
|
@ foreach $node nonindex@
|
|
@ include m2c_setup_node.m2i@
|
|
@ if $node.settable == 1@
|
|
|
|
/* $m2c_node_summary */
|
|
case COLUMN_$node.uc:
|
|
rc = ${node}_undo(rowreq_ctx);
|
|
break;
|
|
@ end@ # settable
|
|
@ end@ # for each column
|
|
|
|
default:
|
|
snmp_log(LOG_ERR,"unknown column %d in _${context}_undo_column\n", column);
|
|
break;
|
|
}
|
|
|
|
return rc;
|
|
} /* _${context}_undo_column */
|
|
|
|
########################################################################
|
|
##
|
|
int
|
|
_mfd_${context}_undo_values(netsnmp_mib_handler *handler,
|
|
netsnmp_handler_registration *reginfo,
|
|
netsnmp_agent_request_info *agtreq_info,
|
|
netsnmp_request_info *requests)
|
|
{
|
|
int rc;
|
|
${context}_rowreq_ctx *rowreq_ctx = (${context}_rowreq_ctx*)
|
|
netsnmp_container_table_row_extract(requests);
|
|
netsnmp_table_request_info * tri;
|
|
|
|
DEBUGMSGTL(("internal:${context}:_mfd_${context}_undo_values","called\n"));
|
|
|
|
netsnmp_assert(NULL != rowreq_ctx);
|
|
|
|
rc = ${context}_undo(rowreq_ctx);
|
|
if (MFD_SUCCESS != rc) {
|
|
/*
|
|
* nothing we can do about it but log it
|
|
*/
|
|
DEBUGMSGTL(("${context}:mfd","error %d from "
|
|
"${context}_undo\n", rc));
|
|
}
|
|
|
|
for(;requests; requests = requests->next) {
|
|
/*
|
|
* set column data
|
|
*/
|
|
tri = netsnmp_extract_table_info(requests);
|
|
if(NULL == tri)
|
|
continue;
|
|
|
|
rc = _${context}_undo_column(rowreq_ctx, requests->requestvb,
|
|
tri->colnum);
|
|
if (MFD_SUCCESS != rc) {
|
|
/*
|
|
* nothing we can do about it but log it
|
|
*/
|
|
DEBUGMSGTL(("${context}:mfd","error %d from "
|
|
"${context}_undo_column\n", rc));
|
|
}
|
|
} /* for results */
|
|
|
|
return SNMP_ERR_NOERROR;
|
|
} /* _mfd_${context}_undo_values */
|
|
|
|
/*----------------------------------------------------------------------
|
|
*
|
|
* SET: irreversible commit
|
|
*
|
|
*---------------------------------------------------------------------*/
|
|
/**
|
|
* @internal
|
|
* commit irreversible actions
|
|
*/
|
|
int
|
|
_mfd_${context}_irreversible_commit(netsnmp_mib_handler *handler,
|
|
netsnmp_handler_registration *reginfo,
|
|
netsnmp_agent_request_info *agtreq_info,
|
|
netsnmp_request_info *requests)
|
|
{
|
|
@ if $m2c_irreversible_commit == 1@
|
|
int rc;
|
|
@ end@
|
|
${context}_rowreq_ctx *rowreq_ctx = (${context}_rowreq_ctx*)
|
|
netsnmp_container_table_row_extract(requests);
|
|
|
|
DEBUGMSGTL(("internal:${context}:_mfd_${context}_irreversible:commit","called\n"));
|
|
|
|
netsnmp_assert(NULL != rowreq_ctx);
|
|
|
|
@ if $m2c_irreversible_commit == 1@
|
|
rc = ${context}_irreversible_commit(rowreq_ctx);
|
|
if (MFD_SUCCESS != rc) {
|
|
netsnmp_request_set_error_all(requests, SNMP_ERR_COMMITFAILED);
|
|
DEBUGMSGTL(("${context}:mfd","error %d from "
|
|
"${context}_irreversible_commit\n", rc));
|
|
}
|
|
|
|
@ end@
|
|
/*
|
|
* check for and handle row creation/deletion
|
|
* and update column exist flags...
|
|
*/
|
|
if (rowreq_ctx->rowreq_flags & MFD_ROW_DELETED) {
|
|
if (! (rowreq_ctx->rowreq_flags & MFD_ROW_CREATED))
|
|
CONTAINER_REMOVE(${context}_if_ctx.container, rowreq_ctx);
|
|
}
|
|
else {
|
|
if (rowreq_ctx->column_set_flags) {
|
|
@if $m2c_table_sparse == 1@
|
|
DEBUGMSGTL(("internal:${context}:_mfd_irreversible_commit",
|
|
"updating exists (%x) w/set (%x) = %x\n",
|
|
rowreq_ctx->column_exists_flags,
|
|
rowreq_ctx->column_set_flags,
|
|
(rowreq_ctx->column_exists_flags |
|
|
rowreq_ctx->column_set_flags)));
|
|
rowreq_ctx->column_exists_flags |=
|
|
rowreq_ctx->column_set_flags;
|
|
@end@ # sparse
|
|
rowreq_ctx->column_set_flags = 0;
|
|
}
|
|
@if ($m2c_table_row_creation == 1)@
|
|
if (rowreq_ctx->rowreq_flags & MFD_ROW_CREATED) {
|
|
rowreq_ctx->rowreq_flags &= ~MFD_ROW_CREATED;
|
|
CONTAINER_INSERT(${context}_if_ctx.container, rowreq_ctx);
|
|
}
|
|
@end@ # creation
|
|
}
|
|
|
|
return SNMP_ERR_NOERROR;
|
|
} /* _mfd_${context}_irreversible_commit */
|
|
|
|
@end@ # settable
|
|
/***********************************************************************
|
|
*
|
|
* DATA ACCESS
|
|
*
|
|
***********************************************************************/
|
|
@ include mfd-access-${m2c_table_access}-defines.m2i@
|
|
@ if $m2c_table_persistent == 1@
|
|
@ include mfd-persistence.m2i@
|
|
@ end@
|
|
|
|
${context}_rowreq_ctx *
|
|
${context}_row_find_by_mib_index(${context}_mib_index *mib_idx)
|
|
{
|
|
${context}_rowreq_ctx *rowreq_ctx;
|
|
oid oid_tmp[MAX_OID_LEN];
|
|
netsnmp_index oid_idx;
|
|
int rc;
|
|
|
|
/*
|
|
* set up storage for OID
|
|
*/
|
|
oid_idx.oids = oid_tmp;
|
|
oid_idx.len = sizeof(oid_tmp)/sizeof(oid);
|
|
|
|
/*
|
|
* convert
|
|
*/
|
|
rc = ${context}_index_to_oid(&oid_idx, mib_idx);
|
|
if (MFD_SUCCESS != rc)
|
|
return NULL;
|
|
|
|
rowreq_ctx = (${context}_rowreq_ctx*)CONTAINER_FIND(${context}_if_ctx.container, &oid_idx);
|
|
|
|
return rowreq_ctx;
|
|
}
|
|
|
|
@ if $m2c_table_refcounts == 1@
|
|
int
|
|
${context}_row_ref_increment(${context}_rowreq_ctx *rowreq_ctx)
|
|
{
|
|
if (NULL == rowreq_ctx)
|
|
return -1;
|
|
|
|
++rowreq_ctx->ref_count;
|
|
DEBUGMSGTL(("${context}:${context}_row_ref_increment",
|
|
"row %p ref count is %d\n",rowreq_ctx,
|
|
rowreq_ctx->ref_count));
|
|
|
|
return MFD_SUCCESS;
|
|
}
|
|
|
|
int
|
|
${context}_row_ref_decrement(${context}_rowreq_ctx *rowreq_ctx)
|
|
{
|
|
if (NULL == rowreq_ctx)
|
|
return -1;
|
|
|
|
if (0 == rowreq_ctx->ref_count) {
|
|
snmp_log(LOG_WARNING,"attempt to decrement ref_count below 0\n");
|
|
return -2;
|
|
}
|
|
--rowreq_ctx->ref_count;
|
|
DEBUGMSGTL(("${context}:${context}_row_ref_decrement",
|
|
"row %p ref count is %d\n",rowreq_ctx,
|
|
rowreq_ctx->ref_count));
|
|
|
|
return MFD_SUCCESS;
|
|
}
|
|
|
|
@ end@ // refcounts
|
|
@end@ # foreach table
|
|
##
|
|
########################################################################
|
|
@if $m2c_mark_boundary == 1@
|
|
/** END code generated by mfd-interface.m2c */
|
|
@end@
|