Blame local/mib2c.array-user.conf

Packit fcad23
## -*- c -*-
Packit fcad23
##
Packit fcad23
## For documentation on the code generated by this configuration file,
Packit fcad23
## see the file agent/helpers/table_array.c.
Packit fcad23
##
Packit fcad23
######################################################################
Packit fcad23
## Do the .h file
Packit fcad23
## @perleval $vars{shortname} =~ s/([A-Z])[a-z]+/$1/g@
Packit fcad23
######################################################################
Packit fcad23
@foreach $i table@
Packit fcad23
@open ${i}.h@
Packit fcad23
/*
Packit fcad23
 * Note: this file originally auto-generated by mib2c
Packit fcad23
 * using mib2c.array-user.conf
Packit fcad23
 *
Packit fcad23
 * Yes, there is lots of code here that you might not use. But it is much
Packit fcad23
 * easier to remove code than to add it!
Packit fcad23
 */
Packit fcad23
#ifndef $i.uc_H
Packit fcad23
#define $i.uc_H
Packit fcad23
Packit fcad23
#ifdef __cplusplus
Packit fcad23
extern "C" {
Packit fcad23
#endif
Packit fcad23
Packit fcad23
    
Packit fcad23
#include <net-snmp/net-snmp-config.h>
Packit fcad23
#include <net-snmp/library/container.h>
Packit fcad23
#include <net-snmp/agent/table_array.h>
Packit fcad23
Packit fcad23
    @eval $ext_index = 0@
Packit fcad23
    @foreach $idx index@
Packit fcad23
        @if "$idx" ne ""@
Packit fcad23
        @eval $found = "external"@
Packit fcad23
        @foreach $c column@
Packit fcad23
            @if "$idx" eq "$c"@
Packit fcad23
               @eval $found = "internal"@
Packit fcad23
            @end@
Packit fcad23
        @end@
Packit fcad23
        /** Index $idx is $found */
Packit fcad23
        @if "$found" eq "external"@
Packit fcad23
           @eval $ext_index = 1@
Packit fcad23
        @end@
Packit fcad23
        @end@
Packit fcad23
    @end@
Packit fcad23
Packit fcad23
typedef struct ${i}_context_s {
Packit fcad23
    netsnmp_index index; /** THIS MUST BE FIRST!!! */
Packit fcad23
Packit fcad23
    /*************************************************************
Packit fcad23
     * You can store data internally in this structure.
Packit fcad23
     *
Packit fcad23
     * TODO: You will probably have to fix a few types here...
Packit fcad23
     */
Packit fcad23
    @if $ext_index != 0@
Packit fcad23
    /** TODO: add storage for external index(s)! */
Packit fcad23
    @end@
Packit fcad23
    @foreach $c column@
Packit fcad23
        /** $c.syntax = $c.type */
Packit fcad23
        @eval $have_type = 0@
Packit fcad23
        @if "$c.type" eq "ASN_OCTET_STR"@
Packit fcad23
            @eval $have_type = 1@
Packit fcad23
            @eval $o_len = "65535"@
Packit fcad23
            @if "$c.syntax" eq "DisplayString"@
Packit fcad23
                @eval $o_len = "255"@
Packit fcad23
            @end@
Packit fcad23
            @if "$c.syntax" eq "SnmpAdminString"@
Packit fcad23
                @eval $o_len = "255"@
Packit fcad23
            @end@
Packit fcad23
            unsigned char $c[$o_len];
Packit fcad23
            long ${c}_len;
Packit fcad23
        @end@
Packit fcad23
        @if "$c.type" eq "ASN_OBJECT_ID"@
Packit fcad23
            @eval $have_type = 1@
Packit fcad23
            oid $c[MAX_OID_LEN];
Packit fcad23
            long ${c}_len;
Packit fcad23
        @end@
Packit fcad23
        @if "$c.type" eq "ASN_UNSIGNED"@
Packit fcad23
            @eval $have_type = 1@
Packit fcad23
            unsigned long $c;
Packit fcad23
        @end@
Packit fcad23
        @if "$c.type" eq "ASN_TIMETICKS"@
Packit fcad23
            @eval $have_type = 1@
Packit fcad23
            unsigned long $c;
Packit fcad23
        @end@
Packit fcad23
        @if "$c.type" eq "ASN_IPADDRESS"@
Packit fcad23
            @eval $have_type = 1@
Packit fcad23
            unsigned long $c;
Packit fcad23
        @end@
Packit fcad23
        @if "$c.type" eq "ASN_UINTEGER"@
Packit fcad23
            @eval $have_type = 1@
Packit fcad23
            unsigned long $c;
Packit fcad23
        @end@
Packit fcad23
        @if "$c.type" eq "ASN_INTEGER"@
Packit fcad23
            @eval $have_type = 1@
Packit fcad23
            long $c;
Packit fcad23
        @end@
Packit fcad23
        @if "$c.type" eq "ASN_COUNTER"@
Packit fcad23
            @eval $have_type = 1@
Packit fcad23
            unsigned long $c;
Packit fcad23
        @end@
Packit fcad23
        @if $have_type == 0@
Packit fcad23
    /** TODO: Is this type correct? */
Packit fcad23
            long $c;
Packit fcad23
        @end@
Packit fcad23
Packit fcad23
    @end@
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * OR
Packit fcad23
     *
Packit fcad23
     * Keep a pointer to your data
Packit fcad23
     */
Packit fcad23
    void * data;
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     *add anything else you want here
Packit fcad23
     */
Packit fcad23
Packit fcad23
} ${i}_context;
Packit fcad23
Packit fcad23
/*************************************************************
Packit fcad23
 * function declarations
Packit fcad23
 */
Packit fcad23
void init_$i(void);
Packit fcad23
void initialize_table_$i(void);
Packit fcad23
const ${i}_context * ${i}_get_by_idx(netsnmp_index *);
Packit fcad23
const ${i}_context * ${i}_get_by_idx_rs(netsnmp_index *,
Packit fcad23
                                        int row_status);
Packit fcad23
int ${i}_get_value(netsnmp_request_info *, netsnmp_index *, netsnmp_table_request_info *);
Packit fcad23
Packit fcad23
Packit fcad23
/*************************************************************
Packit fcad23
 * oid declarations
Packit fcad23
 */
Packit fcad23
extern const oid ${i}_oid[];
Packit fcad23
extern const size_t ${i}_oid_len;
Packit fcad23
Packit fcad23
#define ${i}_TABLE_OID $i.commaoid
Packit fcad23
    
Packit fcad23
/*************************************************************
Packit fcad23
 * column number definitions for table $i
Packit fcad23
 */
Packit fcad23
@eval $minv = 0xffffffff@
Packit fcad23
@eval $maxv = 0@
Packit fcad23
@foreach $c column@
Packit fcad23
#define COLUMN_$c.uc $c.subid
Packit fcad23
@if ! $c.noaccess@
Packit fcad23
@eval $minv = min($minv, $c.subid)@
Packit fcad23
@eval $maxv = max($maxv, $c.subid)@
Packit fcad23
@end@
Packit fcad23
@if "$c.syntax" eq "RowStatus"@
Packit fcad23
   @eval $rs_name = "$c"@
Packit fcad23
@end@
Packit fcad23
@if "$c.syntax" eq "StorageType"@
Packit fcad23
   @eval $st_name = "$c"@
Packit fcad23
@end@
Packit fcad23
@end@
Packit fcad23
#define ${i}_COL_MIN $minv
Packit fcad23
#define ${i}_COL_MAX $maxv
Packit fcad23
Packit fcad23
/* comment out the following line if you don't want a custom sort  */
Packit fcad23
#define ${i}_CUSTOM_SORT
Packit fcad23
Packit fcad23
@if "$rs_name" ne ""@
Packit fcad23
/* uncommend the following line if you allow modifications to an
Packit fcad23
 * active row */
Packit fcad23
/** define ${i}_CAN_MODIFY_ACTIVE_ROW */
Packit fcad23
Packit fcad23
@end@
Packit fcad23
@if $i.settable@
Packit fcad23
int ${i}_extract_index( ${i}_context * ctx, netsnmp_index * hdr );
Packit fcad23
Packit fcad23
void ${i}_set_reserve1( netsnmp_request_group * );
Packit fcad23
void ${i}_set_reserve2( netsnmp_request_group * );
Packit fcad23
void ${i}_set_action( netsnmp_request_group * );
Packit fcad23
void ${i}_set_commit( netsnmp_request_group * );
Packit fcad23
void ${i}_set_free( netsnmp_request_group * );
Packit fcad23
void ${i}_set_undo( netsnmp_request_group * );
Packit fcad23
Packit fcad23
${i}_context * ${i}_duplicate_row( ${i}_context* );
Packit fcad23
netsnmp_index * ${i}_delete_row( ${i}_context* );
Packit fcad23
Packit fcad23
@if "$rs_name" ne ""@
Packit fcad23
int ${i}_can_activate(${i}_context *undo_ctx,
Packit fcad23
                      ${i}_context *row_ctx,
Packit fcad23
                      netsnmp_request_group * rg);
Packit fcad23
int ${i}_can_deactivate(${i}_context *undo_ctx,
Packit fcad23
                        ${i}_context *row_ctx,
Packit fcad23
                        netsnmp_request_group * rg);
Packit fcad23
@end@
Packit fcad23
int ${i}_can_delete(${i}_context *undo_ctx,
Packit fcad23
                    ${i}_context *row_ctx,
Packit fcad23
                    netsnmp_request_group * rg);
Packit fcad23
    
Packit fcad23
    
Packit fcad23
@if $i.creatable@
Packit fcad23
${i}_context * ${i}_create_row( netsnmp_index* );
Packit fcad23
@end@
Packit fcad23
@end@
Packit fcad23
Packit fcad23
#ifdef ${i}_CUSTOM_SORT
Packit fcad23
${i}_context * ${i}_get( const char *name, int len );
Packit fcad23
#endif
Packit fcad23
Packit fcad23
#ifdef __cplusplus
Packit fcad23
}
Packit fcad23
#endif
Packit fcad23
Packit fcad23
#endif /** $i.uc_H */
Packit fcad23
@end@
Packit fcad23
######################################################################
Packit fcad23
## Do the .c file
Packit fcad23
######################################################################
Packit fcad23
@foreach $i table@
Packit fcad23
@open ${i}.c@
Packit fcad23
/*
Packit fcad23
 * Note: this file originally auto-generated by mib2c
Packit fcad23
 * using mib2c.array-user.conf
Packit fcad23
 *
Packit fcad23
 *
Packit fcad23
 * For help understanding NET-SNMP in general, please check the 
Packit fcad23
 *     documentation and FAQ at:
Packit fcad23
 *
Packit fcad23
 *     http://www.net-snmp.org/
Packit fcad23
 *
Packit fcad23
 *
Packit fcad23
 * For help understanding this code, the agent and how it processes
Packit fcad23
 *     requests, please check the following references.
Packit fcad23
 *
Packit fcad23
 *     http://www.net-snmp.org/tutorial-5/
Packit fcad23
 *
Packit fcad23
 *
Packit fcad23
 * You can also join the #net-snmp channel on irc.freenode.net
Packit fcad23
 *     and ask for help there.
Packit fcad23
 *
Packit fcad23
 *
Packit fcad23
 * And if all else fails, send a detailed message to the developers
Packit fcad23
 *     describing the problem you are having to:
Packit fcad23
 *
Packit fcad23
 *    net-snmp-coders@lists.sourceforge.net
Packit fcad23
 *
Packit fcad23
 *
Packit fcad23
 * Yes, there is lots of code here that you might not use. But it is much
Packit fcad23
 * easier to remove code than to add it!
Packit fcad23
 */
Packit fcad23
#include <net-snmp/net-snmp-config.h>
Packit fcad23
#include <net-snmp/net-snmp-includes.h>
Packit fcad23
#include <net-snmp/agent/net-snmp-agent-includes.h>
Packit fcad23
Packit fcad23
#include <net-snmp/library/snmp_assert.h>
Packit fcad23
Packit fcad23
#include "${i}.h"
Packit fcad23
Packit fcad23
static     netsnmp_handler_registration *my_handler = NULL;
Packit fcad23
static     netsnmp_table_array_callbacks cb;
Packit fcad23
Packit fcad23
const oid ${i}_oid[] = { ${i}_TABLE_OID };
Packit fcad23
const size_t ${i}_oid_len = OID_LENGTH(${i}_oid);
Packit fcad23
Packit fcad23
Packit fcad23
#ifdef ${i}_CUSTOM_SORT
Packit fcad23
/************************************************************
Packit fcad23
 * keep binary tree to find context by name
Packit fcad23
 */
Packit fcad23
static int ${i}_cmp( const void *lhs, const void *rhs );
Packit fcad23
Packit fcad23
/************************************************************
Packit fcad23
 * compare two context pointers here. Return -1 if lhs < rhs,
Packit fcad23
 * 0 if lhs == rhs, and 1 if lhs > rhs.
Packit fcad23
 */
Packit fcad23
static int
Packit fcad23
${i}_cmp( const void *lhs, const void *rhs )
Packit fcad23
{
Packit fcad23
    ${i}_context *context_l =
Packit fcad23
        (${i}_context *)lhs;
Packit fcad23
    ${i}_context *context_r =
Packit fcad23
        (${i}_context *)rhs;
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * check primary key, then secondary. Add your own code if
Packit fcad23
     * there are more than 2 keys
Packit fcad23
     */
Packit fcad23
    int rc;
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * TODO: implement compare. Remove this ifdef code and
Packit fcad23
     * add your own code here.
Packit fcad23
     */
Packit fcad23
#ifdef TABLE_CONTAINER_TODO
Packit fcad23
    snmp_log(LOG_ERR,
Packit fcad23
             "${i}_compare not implemented! Container order undefined\n" );
Packit fcad23
    return 0;
Packit fcad23
#endif
Packit fcad23
    
Packit fcad23
    /*
Packit fcad23
     * EXAMPLE (assuming you want to sort on a name):
Packit fcad23
     *   
Packit fcad23
     * rc = strcmp( context_l->xxName, context_r->xxName );
Packit fcad23
     *
Packit fcad23
     * if(rc)
Packit fcad23
     *   return rc;
Packit fcad23
     *
Packit fcad23
     * TODO: fix secondary keys (or delete if there are none)
Packit fcad23
     *
Packit fcad23
     * if(context_l->yy < context_r->yy) 
Packit fcad23
     *   return -1;
Packit fcad23
     *
Packit fcad23
     * return (context_l->yy == context_r->yy) ? 0 : 1;
Packit fcad23
     */
Packit fcad23
}
Packit fcad23
Packit fcad23
/************************************************************
Packit fcad23
 * search tree
Packit fcad23
 */
Packit fcad23
/** TODO: set additional indexes as parameters */
Packit fcad23
${i}_context *
Packit fcad23
${i}_get( const char *name, int len )
Packit fcad23
{
Packit fcad23
    ${i}_context tmp;
Packit fcad23
Packit fcad23
    /** we should have a custom container */
Packit fcad23
    netsnmp_assert(cb.container->next != NULL);
Packit fcad23
    
Packit fcad23
    /*
Packit fcad23
     * TODO: implement compare. Remove this ifdef code and
Packit fcad23
     * add your own code here.
Packit fcad23
     */
Packit fcad23
#ifdef TABLE_CONTAINER_TODO
Packit fcad23
    snmp_log(LOG_ERR, "${i}_get not implemented!\n" );
Packit fcad23
    return NULL;
Packit fcad23
#endif
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * EXAMPLE:
Packit fcad23
     *
Packit fcad23
     * if(len > sizeof(tmp.xxName))
Packit fcad23
     *   return NULL;
Packit fcad23
     *
Packit fcad23
     * strncpy( tmp.xxName, name, sizeof(tmp.xxName) );
Packit fcad23
     * tmp.xxName_len = len;
Packit fcad23
     *
Packit fcad23
     * return CONTAINER_FIND(cb.container->next, &tmp);
Packit fcad23
     */
Packit fcad23
}
Packit fcad23
#endif
Packit fcad23
Packit fcad23
Packit fcad23
/************************************************************
Packit fcad23
 * Initializes the $i module
Packit fcad23
 */
Packit fcad23
void
Packit fcad23
init_$i(void)
Packit fcad23
{
Packit fcad23
    initialize_table_$i();
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * TODO: perform any startup stuff here, such as
Packit fcad23
     * populating the table with initial data.
Packit fcad23
     *
Packit fcad23
     * ${i}_context * new_row = create_row(index);
Packit fcad23
     * CONTAINER_INSERT(cb.container,new_row);
Packit fcad23
     */
Packit fcad23
}
Packit fcad23
Packit fcad23
@if $i.settable@
Packit fcad23
/************************************************************
Packit fcad23
 * the *_row_copy routine
Packit fcad23
 */
Packit fcad23
static int ${i}_row_copy(${i}_context * dst,
Packit fcad23
                         ${i}_context * src)
Packit fcad23
{
Packit fcad23
    if(!dst||!src)
Packit fcad23
        return 1;
Packit fcad23
        
Packit fcad23
    /*
Packit fcad23
     * copy index, if provided
Packit fcad23
     */
Packit fcad23
    if(dst->index.oids)
Packit fcad23
        free(dst->index.oids);
Packit fcad23
    if(snmp_clone_mem( (void*)&dst->index.oids, src->index.oids,
Packit fcad23
                           src->index.len * sizeof(oid) )) {
Packit fcad23
        dst->index.oids = NULL;
Packit fcad23
        return 1;
Packit fcad23
    }
Packit fcad23
    dst->index.len = src->index.len;
Packit fcad23
    
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * copy components into the context structure
Packit fcad23
     */
Packit fcad23
    @if $ext_index != 0@
Packit fcad23
    /** TODO: add code for external index(s)! */
Packit fcad23
    @end@
Packit fcad23
    @foreach $c column@
Packit fcad23
    @eval $have_type = 0@
Packit fcad23
    @if "$c.type" eq "ASN_OCTET_STR"@
Packit fcad23
    @eval $have_type = 1@
Packit fcad23
    memcpy( dst->$c, src->$c, src->${c}_len );
Packit fcad23
    dst->${c}_len = src->${c}_len;
Packit fcad23
    @end@
Packit fcad23
    @if "$c.type" eq "ASN_OBJECT_ID"@
Packit fcad23
    @eval $have_type = 1@
Packit fcad23
    memcpy( dst->$c, src->$c, src->${c}_len );
Packit fcad23
    dst->${c}_len = src->${c}_len;
Packit fcad23
    @end@
Packit fcad23
    @if $have_type == 0@
Packit fcad23
    dst->$c = src->$c;
Packit fcad23
    @end@
Packit fcad23
Packit fcad23
    @end@
Packit fcad23
    return 0;
Packit fcad23
}
Packit fcad23
Packit fcad23
/**
Packit fcad23
 * the *_extract_index routine
Packit fcad23
 *
Packit fcad23
 * This routine is called when a set request is received for an index
Packit fcad23
 * that was not found in the table container. Here, we parse the oid
Packit fcad23
 * in the the individual index components and copy those indexes to the
Packit fcad23
 * context. Then we make sure the indexes for the new row are valid.
Packit fcad23
 */
Packit fcad23
int
Packit fcad23
${i}_extract_index( ${i}_context * ctx, netsnmp_index * hdr )
Packit fcad23
{
Packit fcad23
    /*
Packit fcad23
     * temporary local storage for extracting oid index
Packit fcad23
     *
Packit fcad23
     * extract index uses varbinds (netsnmp_variable_list) to parse
Packit fcad23
     * the index OID into the individual components for each index part.
Packit fcad23
     */
Packit fcad23
    @if $ext_index != 0@
Packit fcad23
    /** TODO: add storage for external index(s)! */
Packit fcad23
    @end@
Packit fcad23
    @eval $first_idx = ""@
Packit fcad23
    @foreach $idx index@
Packit fcad23
        @if "$first_idx" eq ""@
Packit fcad23
        @eval $first_idx = $idx@
Packit fcad23
        @end@
Packit fcad23
    netsnmp_variable_list var_$idx;
Packit fcad23
    @end@
Packit fcad23
    int err;
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * copy index, if provided
Packit fcad23
     */
Packit fcad23
    if(hdr) {
Packit fcad23
        netsnmp_assert(ctx->index.oids == NULL);
Packit fcad23
        if((hdr->len > MAX_OID_LEN) ||
Packit fcad23
           snmp_clone_mem( (void*)&ctx->index.oids, hdr->oids,
Packit fcad23
                           hdr->len * sizeof(oid) )) {
Packit fcad23
            return -1;
Packit fcad23
        }
Packit fcad23
        ctx->index.len = hdr->len;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * initialize variable that will hold each component of the index.
Packit fcad23
     * If there are multiple indexes for the table, the variable_lists
Packit fcad23
     * need to be linked together, in order.
Packit fcad23
     */
Packit fcad23
    @if $ext_index != 0@
Packit fcad23
       /** TODO: add code for external index(s)! */
Packit fcad23
    @end@
Packit fcad23
    @foreach $idx index@
Packit fcad23
       memset( &var_$idx, 0x00, sizeof(var_$idx) );
Packit fcad23
       var_${idx}.type = $idx.type; /* type hint for parse_oid_indexes */
Packit fcad23
       /** TODO: link this index to the next, or NULL for the last one */
Packit fcad23
#ifdef TABLE_CONTAINER_TODO
Packit fcad23
    snmp_log(LOG_ERR, "${i}_extract_index index list not implemented!\n" );
Packit fcad23
    return 0;
Packit fcad23
#else
Packit fcad23
       var_${idx}.next_variable = &var_XX;
Packit fcad23
#endif
Packit fcad23
Packit fcad23
    @end@
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * parse the oid into the individual index components
Packit fcad23
     */
Packit fcad23
    err = parse_oid_indexes( hdr->oids, hdr->len, &var_$first_idx );
Packit fcad23
    if (err == SNMP_ERR_NOERROR) {
Packit fcad23
       /*
Packit fcad23
        * copy index components into the context structure
Packit fcad23
        */
Packit fcad23
       @foreach $idx index@
Packit fcad23
          @eval $found = "external"@
Packit fcad23
          @foreach $c column@
Packit fcad23
              @if "$idx" eq "$c"@
Packit fcad23
                 @eval $found = "internal"@
Packit fcad23
              @end@
Packit fcad23
          @end@
Packit fcad23
          @if "$found" eq "external"@
Packit fcad23
              /** skipping external index $idx */
Packit fcad23
          @end@
Packit fcad23
          @if "$found" eq "internal"@
Packit fcad23
             @eval $have_type = 0@
Packit fcad23
             @if "$idx.type" eq "ASN_OCTET_STR"@
Packit fcad23
             @eval $have_type = 1@
Packit fcad23
                if(var_${idx}.val_len > sizeof(ctx->$idx))
Packit fcad23
                   err = -1;
Packit fcad23
                else
Packit fcad23
                    memcpy( ctx->$idx, var_${idx}.val.string, var_${idx}.val_len );
Packit fcad23
                ctx->${idx}_len = var_${idx}.val_len;
Packit fcad23
             @end@
Packit fcad23
             @if "$idx.type" eq "ASN_OBJECT_ID"@
Packit fcad23
             @eval $have_type = 1@
Packit fcad23
                memcpy( ctx->$idx, var_${idx}.val.string, var_${idx}.val_len );
Packit fcad23
                ctx->${idx}_len = var_${idx}.val_len;
Packit fcad23
             @end@
Packit fcad23
             @if $have_type == 0@
Packit fcad23
                ctx->$idx = *var_${idx}.val.integer;
Packit fcad23
             @end@
Packit fcad23
          @end@
Packit fcad23
   
Packit fcad23
       @end@
Packit fcad23
   
Packit fcad23
       @foreach $c index@
Packit fcad23
           /*
Packit fcad23
            * TODO: check index for valid values. For EXAMPLE:
Packit fcad23
            *
Packit fcad23
          @eval $have_check = 0@
Packit fcad23
          @if "$c.type" eq "ASN_IPADDRESS"@
Packit fcad23
              @eval $have_check = 1@
Packit fcad23
              * if ( XXX_check_ip( *var_${c}.val.integer ) ) {
Packit fcad23
          @end@
Packit fcad23
          @if "$c.type" eq "ASN_OBJECT_ID"@
Packit fcad23
              @eval $have_check = 1@
Packit fcad23
              * if ( XXX_check_oid( var_${c}.val.objid, var_${c}.val_len /
Packit fcad23
                                    sizeof(oid) ) ) {
Packit fcad23
          @end@
Packit fcad23
          @if "$c.type" eq "ASN_OCTET_STR"@
Packit fcad23
              @eval $have_check = 1@
Packit fcad23
              * if ( XXX_check_value( var_${c}.val.string, XXX ) ) {
Packit fcad23
          @end@
Packit fcad23
          @if $have_check != 1@
Packit fcad23
              * if ( *var_${c}.val.integer != XXX ) {
Packit fcad23
          @end@
Packit fcad23
          *    err = -1;
Packit fcad23
          * }
Packit fcad23
          */
Packit fcad23
       @end@
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * parsing may have allocated memory. free it.
Packit fcad23
     */
Packit fcad23
    snmp_reset_var_buffers( &var_$first_idx );
Packit fcad23
Packit fcad23
    return err;
Packit fcad23
}
Packit fcad23
Packit fcad23
@if "$rs_name" ne ""@
Packit fcad23
/************************************************************
Packit fcad23
 * the *_can_activate routine is called
Packit fcad23
 * when a row is changed to determine if all the values
Packit fcad23
 * set are consistent with the row's rules for a row status
Packit fcad23
 * of ACTIVE.
Packit fcad23
 *
Packit fcad23
 * return 1 if the row could be ACTIVE
Packit fcad23
 * return 0 if the row is not ready for the ACTIVE state
Packit fcad23
 */
Packit fcad23
int ${i}_can_activate(${i}_context *undo_ctx,
Packit fcad23
                      ${i}_context *row_ctx,
Packit fcad23
                      netsnmp_request_group * rg)
Packit fcad23
{
Packit fcad23
    /*
Packit fcad23
     * TODO: check for activation requirements here
Packit fcad23
     */
Packit fcad23
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * be optimistic.
Packit fcad23
     */
Packit fcad23
    return 1;
Packit fcad23
}
Packit fcad23
Packit fcad23
/************************************************************
Packit fcad23
 * the *_can_deactivate routine is called when a row that is
Packit fcad23
 * currently ACTIVE is set to a state other than ACTIVE. If
Packit fcad23
 * there are conditions in which a row should not be allowed
Packit fcad23
 * to transition out of the ACTIVE state (such as the row being
Packit fcad23
 * referred to by another row or table), check for them here.
Packit fcad23
 *
Packit fcad23
 * return 1 if the row can be set to a non-ACTIVE state
Packit fcad23
 * return 0 if the row must remain in the ACTIVE state
Packit fcad23
 */
Packit fcad23
int ${i}_can_deactivate(${i}_context *undo_ctx,
Packit fcad23
                        ${i}_context *row_ctx,
Packit fcad23
                        netsnmp_request_group * rg)
Packit fcad23
{
Packit fcad23
    /*
Packit fcad23
     * TODO: check for deactivation requirements here
Packit fcad23
     */
Packit fcad23
    return 1;
Packit fcad23
}
Packit fcad23
Packit fcad23
@end@
Packit fcad23
/************************************************************
Packit fcad23
 * the *_can_delete routine is called to determine if a row
Packit fcad23
 * can be deleted.
Packit fcad23
 *
Packit fcad23
 * return 1 if the row can be deleted
Packit fcad23
 * return 0 if the row cannot be deleted
Packit fcad23
 */
Packit fcad23
int ${i}_can_delete(${i}_context *undo_ctx,
Packit fcad23
                    ${i}_context *row_ctx,
Packit fcad23
                    netsnmp_request_group * rg)
Packit fcad23
{
Packit fcad23
@if "$rs_name" ne ""@
Packit fcad23
    /*
Packit fcad23
     * probably shouldn't delete a row that we can't
Packit fcad23
     * deactivate.
Packit fcad23
     */
Packit fcad23
    if(${i}_can_deactivate(undo_ctx,row_ctx,rg) != 1)
Packit fcad23
        return 0;
Packit fcad23
@end@
Packit fcad23
    
Packit fcad23
    /*
Packit fcad23
     * TODO: check for other deletion requirements here
Packit fcad23
     */
Packit fcad23
    return 1;
Packit fcad23
}
Packit fcad23
Packit fcad23
@if $i.creatable@
Packit fcad23
/************************************************************
Packit fcad23
 * the *_create_row routine is called by the table handler
Packit fcad23
 * to create a new row for a given index. If you need more
Packit fcad23
 * information (such as column values) to make a decision
Packit fcad23
 * on creating rows, you must create an initial row here
Packit fcad23
 * (to hold the column values), and you can examine the
Packit fcad23
 * situation in more detail in the *_set_reserve1 or later
Packit fcad23
 * states of set processing. Simple check for a NULL undo_ctx
Packit fcad23
 * in those states and do detailed creation checking there.
Packit fcad23
 *
Packit fcad23
 * returns a newly allocated ${i}_context
Packit fcad23
 *   structure if the specified indexes are not illegal
Packit fcad23
 * returns NULL for errors or illegal index values.
Packit fcad23
 */
Packit fcad23
${i}_context *
Packit fcad23
${i}_create_row( netsnmp_index* hdr)
Packit fcad23
{
Packit fcad23
    ${i}_context * ctx =
Packit fcad23
        SNMP_MALLOC_TYPEDEF(${i}_context);
Packit fcad23
    if(!ctx)
Packit fcad23
        return NULL;
Packit fcad23
        
Packit fcad23
    /*
Packit fcad23
     * TODO: check indexes, if necessary.
Packit fcad23
     */
Packit fcad23
    if(${i}_extract_index( ctx, hdr )) {
Packit fcad23
        if (NULL != ctx->index.oids)
Packit fcad23
            free(ctx->index.oids);
Packit fcad23
        free(ctx);
Packit fcad23
        return NULL;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /* netsnmp_mutex_init(ctx->lock);
Packit fcad23
       netsnmp_mutex_lock(ctx->lock); */
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * TODO: initialize any default values here. This is also
Packit fcad23
     * first place you really should allocate any memory for
Packit fcad23
     * yourself to use.  If you allocated memory earlier,
Packit fcad23
     * make sure you free it for earlier error cases!
Packit fcad23
     */
Packit fcad23
    /**
Packit fcad23
     @foreach $c column@
Packit fcad23
     @if $c.settable@
Packit fcad23
     ctx->$c = 0;
Packit fcad23
     @end@
Packit fcad23
     @end@
Packit fcad23
    */
Packit fcad23
Packit fcad23
    return ctx;
Packit fcad23
}
Packit fcad23
@end@
Packit fcad23
Packit fcad23
/************************************************************
Packit fcad23
 * the *_duplicate row routine
Packit fcad23
 */
Packit fcad23
${i}_context *
Packit fcad23
${i}_duplicate_row( ${i}_context * row_ctx)
Packit fcad23
{
Packit fcad23
    ${i}_context * dup;
Packit fcad23
Packit fcad23
    if(!row_ctx)
Packit fcad23
        return NULL;
Packit fcad23
Packit fcad23
    dup = SNMP_MALLOC_TYPEDEF(${i}_context);
Packit fcad23
    if(!dup)
Packit fcad23
        return NULL;
Packit fcad23
        
Packit fcad23
    if(${i}_row_copy(dup,row_ctx)) {
Packit fcad23
        free(dup);
Packit fcad23
        dup = NULL;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    return dup;
Packit fcad23
}
Packit fcad23
Packit fcad23
/************************************************************
Packit fcad23
 * the *_delete_row method is called to delete a row.
Packit fcad23
 */
Packit fcad23
netsnmp_index * ${i}_delete_row( ${i}_context * ctx )
Packit fcad23
{
Packit fcad23
  /* netsnmp_mutex_destroy(ctx->lock); */
Packit fcad23
Packit fcad23
    if(ctx->index.oids)
Packit fcad23
        free(ctx->index.oids);
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * TODO: release any memory you allocated here...
Packit fcad23
     */
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * release header
Packit fcad23
     */
Packit fcad23
    free( ctx );
Packit fcad23
Packit fcad23
    return NULL;
Packit fcad23
}
Packit fcad23
Packit fcad23
Packit fcad23
/************************************************************
Packit fcad23
 * RESERVE is used to check the syntax of all the variables
Packit fcad23
 * provided, that the values being set are sensible and consistent,
Packit fcad23
 * and to allocate any resources required for performing the SET.
Packit fcad23
 * After this stage, the expectation is that the set ought to
Packit fcad23
 * succeed, though this is not guaranteed. (In fact, with the UCD
Packit fcad23
 * agent, this is done in two passes - RESERVE1, and
Packit fcad23
 * RESERVE2, to allow for dependancies between variables).
Packit fcad23
 *
Packit fcad23
 * BEFORE calling this routine, the agent will call duplicate_row
Packit fcad23
 * to create a copy of the row (unless this is a new row; i.e.
Packit fcad23
 * row_created == 1).
Packit fcad23
 *
Packit fcad23
 * next state -> SET_RESERVE2 || SET_FREE
Packit fcad23
 */
Packit fcad23
void ${i}_set_reserve1( netsnmp_request_group *rg )
Packit fcad23
{
Packit fcad23
    ${i}_context *row_ctx =
Packit fcad23
            (${i}_context *)rg->existing_row;
Packit fcad23
    ${i}_context *undo_ctx =
Packit fcad23
            (${i}_context *)rg->undo_info;
Packit fcad23
    netsnmp_variable_list *var;
Packit fcad23
    netsnmp_request_group_item *current;
Packit fcad23
    int rc;
Packit fcad23
Packit fcad23
    @if "$st_name" ne ""@
Packit fcad23
        /*
Packit fcad23
         * Block all attempts to modify a readOnly row
Packit fcad23
         */
Packit fcad23
    if( row_ctx && (row_ctx->$st_name == SNMP_STORAGE_READONLY) ) {
Packit fcad23
        netsnmp_set_mode_request_error(MODE_SET_BEGIN, rg->list->ri,
Packit fcad23
                                       SNMP_ERR_NOTWRITABLE);
Packit fcad23
        return;
Packit fcad23
    }
Packit fcad23
    @end@
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * TODO: loop through columns, check syntax and lengths. For
Packit fcad23
     * columns which have no dependencies, you could also move
Packit fcad23
     * the value/range checking here to attempt to catch error
Packit fcad23
     * cases as early as possible.
Packit fcad23
     */
Packit fcad23
    for( current = rg->list; current; current = current->next ) {
Packit fcad23
Packit fcad23
        var = current->ri->requestvb;
Packit fcad23
        rc = SNMP_ERR_NOERROR;
Packit fcad23
Packit fcad23
        switch(current->tri->colnum) {
Packit fcad23
Packit fcad23
        @foreach $c column@
Packit fcad23
        @if $c.settable@
Packit fcad23
        case COLUMN_$c.uc:
Packit fcad23
            /** $c.syntax = $c.type */
Packit fcad23
            @if $c.needlength@
Packit fcad23
            /* or possibly 'netsnmp_check_vb_type_and_size' */
Packit fcad23
            rc = netsnmp_check_vb_type_and_max_size(var, $c.type,
Packit fcad23
                                                    sizeof(row_ctx->$c));
Packit fcad23
            @else@
Packit fcad23
            /* or possibly 'netsnmp_check_vb_int_range' */
Packit fcad23
            rc = netsnmp_check_vb_int( var );
Packit fcad23
            @end@
Packit fcad23
        break;
Packit fcad23
Packit fcad23
        @end@
Packit fcad23
        @end@
Packit fcad23
        default: /** We shouldn't get here */
Packit fcad23
            rc = SNMP_ERR_GENERR;
Packit fcad23
            snmp_log(LOG_ERR, "unknown column in "
Packit fcad23
                     "${i}_set_reserve1\n");
Packit fcad23
        }
Packit fcad23
Packit fcad23
        if (rc)
Packit fcad23
           netsnmp_set_mode_request_error(MODE_SET_BEGIN, current->ri, rc );
Packit fcad23
        rg->status = SNMP_MAX( rg->status, current->ri->status );
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * done with all the columns. Could check row related
Packit fcad23
     * requirements here.
Packit fcad23
     */
Packit fcad23
}
Packit fcad23
Packit fcad23
void ${i}_set_reserve2( netsnmp_request_group *rg )
Packit fcad23
{
Packit fcad23
    ${i}_context *row_ctx = (${i}_context *)rg->existing_row;
Packit fcad23
    ${i}_context *undo_ctx = (${i}_context *)rg->undo_info;
Packit fcad23
    netsnmp_request_group_item *current;
Packit fcad23
    netsnmp_variable_list *var;
Packit fcad23
    int rc;
Packit fcad23
Packit fcad23
    rg->rg_void = rg->list->ri;
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * TODO: loop through columns, check for valid
Packit fcad23
     * values and any range constraints.
Packit fcad23
     */
Packit fcad23
    for( current = rg->list; current; current = current->next ) {
Packit fcad23
Packit fcad23
        var = current->ri->requestvb;
Packit fcad23
        rc = SNMP_ERR_NOERROR;
Packit fcad23
Packit fcad23
        switch(current->tri->colnum) {
Packit fcad23
Packit fcad23
        @foreach $c column@
Packit fcad23
        @if $c.settable@
Packit fcad23
        case COLUMN_$c.uc:
Packit fcad23
            /** $c.syntax = $c.type */
Packit fcad23
            @eval $have_check = 0@
Packit fcad23
            @if "$c" eq "$st_name"@
Packit fcad23
                @eval $have_check = 1@
Packit fcad23
                rc = netsnmp_check_vb_storagetype(current->ri->requestvb,
Packit fcad23
                                                  undo_ctx ?
Packit fcad23
                                                  undo_ctx->$c:0);
Packit fcad23
            @end@
Packit fcad23
            @if "$c" eq "$rs_name"@
Packit fcad23
                @eval $have_check = 1@
Packit fcad23
                rc = netsnmp_check_vb_rowstatus(current->ri->requestvb,
Packit fcad23
                                                undo_ctx ?
Packit fcad23
                                                undo_ctx->$c:0);
Packit fcad23
                rg->rg_void = current->ri;
Packit fcad23
            @end@
Packit fcad23
            @if "$c.syntax" eq "TruthValue"@
Packit fcad23
                @eval $have_check = 1@
Packit fcad23
                rc = netsnmp_check_vb_truthvalue(current->ri->requestvb);
Packit fcad23
            @end@
Packit fcad23
            @if $have_check == 0@
Packit fcad23
                    /*
Packit fcad23
                     * TODO: routine to check valid values
Packit fcad23
                     *
Packit fcad23
                     * EXAMPLE:
Packit fcad23
                     *
Packit fcad23
                @if "$c.type" eq "ASN_IPADDRESS"@
Packit fcad23
                    @eval $have_check = 1@
Packit fcad23
                    * if ( XXX_check_ip( *var->val.integer ) ) {
Packit fcad23
                @end@
Packit fcad23
                @if "$c.type" eq "ASN_OBJECT_ID"@
Packit fcad23
                    @eval $have_check = 1@
Packit fcad23
                    * if ( XXX_check_oid( var ) ) {
Packit fcad23
                @end@
Packit fcad23
                @if "$c.type" eq "ASN_OCTET_STR"@
Packit fcad23
                    @eval $have_check = 1@
Packit fcad23
                    * if ( XXX_check_value( var->val.string, XXX ) ) {
Packit fcad23
                @end@
Packit fcad23
                @if $have_check != 1@
Packit fcad23
                    * if ( *var->val.integer != XXX ) {
Packit fcad23
                @end@
Packit fcad23
                *    rc = SNMP_ERR_INCONSISTENTVALUE;
Packit fcad23
                *    rc = SNMP_ERR_BADVALUE;
Packit fcad23
                * }
Packit fcad23
                */
Packit fcad23
            @end@
Packit fcad23
        break;
Packit fcad23
Packit fcad23
        @end@
Packit fcad23
        @end@
Packit fcad23
        default: /** We shouldn't get here */
Packit fcad23
            netsnmp_assert(0); /** why wasn't this caught in reserve1? */
Packit fcad23
        }
Packit fcad23
Packit fcad23
        if (rc)
Packit fcad23
           netsnmp_set_mode_request_error(MODE_SET_BEGIN, current->ri, rc);
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * done with all the columns. Could check row related
Packit fcad23
     * requirements here.
Packit fcad23
     */
Packit fcad23
}
Packit fcad23
Packit fcad23
/************************************************************
Packit fcad23
 * Assuming that the RESERVE phases were successful, the next
Packit fcad23
 * stage is indicated by the action value ACTION. This is used
Packit fcad23
 * to actually implement the set operation. However, this must
Packit fcad23
 * either be done into temporary (persistent) storage, or the
Packit fcad23
 * previous value stored similarly, in case any of the subsequent
Packit fcad23
 * ACTION calls fail.
Packit fcad23
 *
Packit fcad23
 * In your case, changes should be made to row_ctx. A copy of
Packit fcad23
 * the original row is in undo_ctx.
Packit fcad23
 */
Packit fcad23
void ${i}_set_action( netsnmp_request_group *rg )
Packit fcad23
{
Packit fcad23
    netsnmp_variable_list *var;
Packit fcad23
    ${i}_context *row_ctx = (${i}_context *)rg->existing_row;
Packit fcad23
    ${i}_context *undo_ctx = (${i}_context *)rg->undo_info;
Packit fcad23
    netsnmp_request_group_item *current;
Packit fcad23
Packit fcad23
    @if "$rs_name" ne ""@
Packit fcad23
    int            row_err = 0;
Packit fcad23
    @end@
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * TODO: loop through columns, copy varbind values
Packit fcad23
     * to context structure for the row.
Packit fcad23
     */
Packit fcad23
    for( current = rg->list; current; current = current->next ) {
Packit fcad23
Packit fcad23
        var = current->ri->requestvb;
Packit fcad23
Packit fcad23
        switch(current->tri->colnum) {
Packit fcad23
Packit fcad23
        @foreach $c column@
Packit fcad23
        @if $c.settable@
Packit fcad23
        case COLUMN_$c.uc:
Packit fcad23
            /** $c.syntax = $c.type */
Packit fcad23
            @eval $have_type = 0@
Packit fcad23
            @if "$c.type" eq "ASN_OCTET_STR"@
Packit fcad23
            @eval $have_type = 1@
Packit fcad23
            memcpy(row_ctx->$c,var->val.string,var->val_len);
Packit fcad23
            row_ctx->${c}_len = var->val_len;
Packit fcad23
            @end@
Packit fcad23
            @if "$c.type" eq "ASN_OBJECT_ID"@
Packit fcad23
            @eval $have_type = 1@
Packit fcad23
            memcpy(row_ctx->$c,var->val.objid,var->val_len);
Packit fcad23
            row_ctx->${c}_len = var->val_len;
Packit fcad23
            @end@
Packit fcad23
            @if $have_type == 0@
Packit fcad23
            row_ctx->$c = *var->val.integer;
Packit fcad23
            @end@
Packit fcad23
        break;
Packit fcad23
Packit fcad23
        @end@
Packit fcad23
        @end@
Packit fcad23
        default: /** We shouldn't get here */
Packit fcad23
            netsnmp_assert(0); /** why wasn't this caught in reserve1? */
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * done with all the columns. Could check row related
Packit fcad23
     * requirements here.
Packit fcad23
     */
Packit fcad23
    @if "$rs_name" ne ""@
Packit fcad23
#ifndef ${i}_CAN_MODIFY_ACTIVE_ROW
Packit fcad23
    if( undo_ctx && RS_IS_ACTIVE(undo_ctx->$rs_name) &&
Packit fcad23
        row_ctx && RS_IS_ACTIVE(row_ctx->$rs_name) ) {
Packit fcad23
            row_err = 1;
Packit fcad23
    }
Packit fcad23
#endif
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * check activation/deactivation
Packit fcad23
     */
Packit fcad23
    row_err = netsnmp_table_array_check_row_status(&cb, rg,
Packit fcad23
                                  row_ctx ? &row_ctx->$rs_name : NULL,
Packit fcad23
                                  undo_ctx ? &undo_ctx->$rs_name : NULL);
Packit fcad23
    if(row_err) {
Packit fcad23
        netsnmp_set_mode_request_error(MODE_SET_BEGIN,
Packit fcad23
                                       (netsnmp_request_info*)rg->rg_void,
Packit fcad23
                                       row_err);
Packit fcad23
        return;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    @end@
Packit fcad23
    /*
Packit fcad23
     * TODO: if you have dependencies on other tables, this would be
Packit fcad23
     * a good place to check those, too.
Packit fcad23
     */
Packit fcad23
}
Packit fcad23
Packit fcad23
/************************************************************
Packit fcad23
 * Only once the ACTION phase has completed successfully, can
Packit fcad23
 * the final COMMIT phase be run. This is used to complete any
Packit fcad23
 * writes that were done into temporary storage, and then release
Packit fcad23
 * any allocated resources. Note that all the code in this phase
Packit fcad23
 * should be "safe" code that cannot possibly fail (cue
Packit fcad23
 * hysterical laughter). The whole intent of the ACTION/COMMIT
Packit fcad23
 * division is that all of the fallible code should be done in
Packit fcad23
 * the ACTION phase, so that it can be backed out if necessary.
Packit fcad23
 *
Packit fcad23
 * BEFORE calling this routine, the agent will update the
Packit fcad23
 * container (inserting a row if row_created == 1, or removing
Packit fcad23
 * the row if row_deleted == 1).
Packit fcad23
 *
Packit fcad23
 * AFTER calling this routine, the agent will delete the
Packit fcad23
 * undo_info.
Packit fcad23
 */
Packit fcad23
void ${i}_set_commit( netsnmp_request_group *rg )
Packit fcad23
{
Packit fcad23
    netsnmp_variable_list *var;
Packit fcad23
    ${i}_context *row_ctx = (${i}_context *)rg->existing_row;
Packit fcad23
    ${i}_context *undo_ctx = (${i}_context *)rg->undo_info;
Packit fcad23
    netsnmp_request_group_item *current;
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * loop through columns
Packit fcad23
     */
Packit fcad23
    for( current = rg->list; current; current = current->next ) {
Packit fcad23
Packit fcad23
        var = current->ri->requestvb;
Packit fcad23
Packit fcad23
        switch(current->tri->colnum) {
Packit fcad23
Packit fcad23
        @foreach $c column@
Packit fcad23
        @if $c.settable@
Packit fcad23
        case COLUMN_$c.uc:
Packit fcad23
            /** $c.syntax = $c.type */
Packit fcad23
        break;
Packit fcad23
Packit fcad23
        @end@
Packit fcad23
        @end@
Packit fcad23
        default: /** We shouldn't get here */
Packit fcad23
            netsnmp_assert(0); /** why wasn't this caught in reserve1? */
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * done with all the columns. Could check row related
Packit fcad23
     * requirements here.
Packit fcad23
     */
Packit fcad23
}
Packit fcad23
Packit fcad23
/************************************************************
Packit fcad23
 * If either of the RESERVE calls fail, the write routines
Packit fcad23
 * are called again with the FREE action, to release any resources
Packit fcad23
 * that have been allocated. The agent will then return a failure
Packit fcad23
 * response to the requesting application.
Packit fcad23
 *
Packit fcad23
 * AFTER calling this routine, the agent will delete undo_info.
Packit fcad23
 */
Packit fcad23
void ${i}_set_free( netsnmp_request_group *rg )
Packit fcad23
{
Packit fcad23
    netsnmp_variable_list *var;
Packit fcad23
    ${i}_context *row_ctx = (${i}_context *)rg->existing_row;
Packit fcad23
    ${i}_context *undo_ctx = (${i}_context *)rg->undo_info;
Packit fcad23
    netsnmp_request_group_item *current;
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * loop through columns
Packit fcad23
     */
Packit fcad23
    for( current = rg->list; current; current = current->next ) {
Packit fcad23
Packit fcad23
        var = current->ri->requestvb;
Packit fcad23
Packit fcad23
        switch(current->tri->colnum) {
Packit fcad23
Packit fcad23
        @foreach $c column@
Packit fcad23
        @if $c.settable@
Packit fcad23
        case COLUMN_$c.uc:
Packit fcad23
            /** $c.syntax = $c.type */
Packit fcad23
        break;
Packit fcad23
Packit fcad23
        @end@
Packit fcad23
        @end@
Packit fcad23
        default: /** We shouldn't get here */
Packit fcad23
            /** should have been logged in reserve1 */
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * done with all the columns. Could check row related
Packit fcad23
     * requirements here.
Packit fcad23
     */
Packit fcad23
}
Packit fcad23
Packit fcad23
/************************************************************
Packit fcad23
 * If the ACTION phase does fail (for example due to an apparently
Packit fcad23
 * valid, but unacceptable value, or an unforeseen problem), then
Packit fcad23
 * the list of write routines are called again, with the UNDO
Packit fcad23
 * action. This requires the routine to reset the value that was
Packit fcad23
 * changed to its previous value (assuming it was actually changed),
Packit fcad23
 * and then to release any resources that had been allocated. As
Packit fcad23
 * with the FREE phase, the agent will then return an indication
Packit fcad23
 * of the error to the requesting application.
Packit fcad23
 *
Packit fcad23
 * BEFORE calling this routine, the agent will update the container
Packit fcad23
 * (remove any newly inserted row, re-insert any removed row).
Packit fcad23
 *
Packit fcad23
 * AFTER calling this routing, the agent will call row_copy
Packit fcad23
 * to restore the data in existing_row from the date in undo_info.
Packit fcad23
 * Then undo_info will be deleted (or existing row, if row_created
Packit fcad23
 * == 1).
Packit fcad23
 */
Packit fcad23
void ${i}_set_undo( netsnmp_request_group *rg )
Packit fcad23
{
Packit fcad23
    netsnmp_variable_list *var;
Packit fcad23
    ${i}_context *row_ctx = (${i}_context *)rg->existing_row;
Packit fcad23
    ${i}_context *undo_ctx = (${i}_context *)rg->undo_info;
Packit fcad23
    netsnmp_request_group_item *current;
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * loop through columns
Packit fcad23
     */
Packit fcad23
    for( current = rg->list; current; current = current->next ) {
Packit fcad23
Packit fcad23
        var = current->ri->requestvb;
Packit fcad23
Packit fcad23
        switch(current->tri->colnum) {
Packit fcad23
Packit fcad23
        @foreach $c column@
Packit fcad23
        @if $c.settable@
Packit fcad23
        case COLUMN_$c.uc:
Packit fcad23
            /** $c.syntax = $c.type */
Packit fcad23
        break;
Packit fcad23
Packit fcad23
        @end@
Packit fcad23
        @end@
Packit fcad23
        default: /** We shouldn't get here */
Packit fcad23
            netsnmp_assert(0); /** why wasn't this caught in reserve1? */
Packit fcad23
        }
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * done with all the columns. Could check row related
Packit fcad23
     * requirements here.
Packit fcad23
     */
Packit fcad23
}
Packit fcad23
Packit fcad23
@end@
Packit fcad23
Packit fcad23
Packit fcad23
/************************************************************
Packit fcad23
 *
Packit fcad23
 * Initialize the $i table by defining its contents and how it's structured
Packit fcad23
 */
Packit fcad23
void
Packit fcad23
initialize_table_$i(void)
Packit fcad23
{
Packit fcad23
    netsnmp_table_registration_info *table_info;
Packit fcad23
Packit fcad23
    if(my_handler) {
Packit fcad23
        snmp_log(LOG_ERR, "initialize_table_${i}_handler called again\n");
Packit fcad23
        return;
Packit fcad23
    }
Packit fcad23
Packit fcad23
    memset(&cb, 0x00, sizeof(cb));
Packit fcad23
Packit fcad23
    /** create the table structure itself */
Packit fcad23
    table_info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info);
Packit fcad23
Packit fcad23
    my_handler = netsnmp_create_handler_registration("$i",
Packit fcad23
                                             netsnmp_table_array_helper_handler,
Packit fcad23
                                             ${i}_oid,
Packit fcad23
                                             ${i}_oid_len,
Packit fcad23
@if $i.settable@
Packit fcad23
                                             HANDLER_CAN_RWRITE
Packit fcad23
@else@
Packit fcad23
                                             HANDLER_CAN_RONLY
Packit fcad23
@end@
Packit fcad23
                                             );
Packit fcad23
            
Packit fcad23
    if (!my_handler || !table_info) {
Packit fcad23
        snmp_log(LOG_ERR, "malloc failed in "
Packit fcad23
                 "initialize_table_${i}_handler\n");
Packit fcad23
        return; /** mallocs failed */
Packit fcad23
    }
Packit fcad23
Packit fcad23
    /***************************************************
Packit fcad23
     * Setting up the table's definition
Packit fcad23
     */
Packit fcad23
    /*
Packit fcad23
     * TODO: add any external indexes here.
Packit fcad23
     */
Packit fcad23
    @if $ext_index != 0@
Packit fcad23
        /** TODO: add code for external index(s)! */
Packit fcad23
    @end@
Packit fcad23
Packit fcad23
    /*
Packit fcad23
     * internal indexes
Packit fcad23
     */
Packit fcad23
    @foreach $idx index@
Packit fcad23
        /** index: $idx */
Packit fcad23
        netsnmp_table_helper_add_index(table_info, $idx.type);
Packit fcad23
    @end@
Packit fcad23
Packit fcad23
    table_info->min_column = ${i}_COL_MIN;
Packit fcad23
    table_info->max_column = ${i}_COL_MAX;
Packit fcad23
Packit fcad23
    /***************************************************
Packit fcad23
     * registering the table with the master agent
Packit fcad23
     */
Packit fcad23
    cb.get_value = ${i}_get_value;
Packit fcad23
    cb.container = netsnmp_container_find("${i}_primary:"
Packit fcad23
                                          "${i}:"
Packit fcad23
                                          "table_container");
Packit fcad23
#ifdef ${i}_CUSTOM_SORT
Packit fcad23
    netsnmp_container_add_index(cb.container,
Packit fcad23
                                netsnmp_container_find("${i}_custom:"
Packit fcad23
                                                       "${i}:"
Packit fcad23
                                                       "table_container"));
Packit fcad23
    cb.container->next->compare = ${i}_cmp;
Packit fcad23
#endif
Packit fcad23
@if $i.settable@
Packit fcad23
    cb.can_set = 1;
Packit fcad23
@if $i.creatable@
Packit fcad23
    cb.create_row = (UserRowMethod*)${i}_create_row;
Packit fcad23
@end@
Packit fcad23
    cb.duplicate_row = (UserRowMethod*)${i}_duplicate_row;
Packit fcad23
    cb.delete_row = (UserRowMethod*)${i}_delete_row;
Packit fcad23
    cb.row_copy = (Netsnmp_User_Row_Operation *)${i}_row_copy;
Packit fcad23
Packit fcad23
@if "$rs_name" ne ""@
Packit fcad23
    cb.can_activate = (Netsnmp_User_Row_Action *)${i}_can_activate;
Packit fcad23
    cb.can_deactivate = (Netsnmp_User_Row_Action *)${i}_can_deactivate;
Packit fcad23
@end@
Packit fcad23
    cb.can_delete = (Netsnmp_User_Row_Action *)${i}_can_delete;
Packit fcad23
Packit fcad23
    cb.set_reserve1 = ${i}_set_reserve1;
Packit fcad23
    cb.set_reserve2 = ${i}_set_reserve2;
Packit fcad23
    cb.set_action = ${i}_set_action;
Packit fcad23
    cb.set_commit = ${i}_set_commit;
Packit fcad23
    cb.set_free = ${i}_set_free;
Packit fcad23
    cb.set_undo = ${i}_set_undo;
Packit fcad23
@end@
Packit fcad23
    DEBUGMSGTL(("initialize_table_$i",
Packit fcad23
                "Registering table $i "
Packit fcad23
                "as a table array\n"));
Packit fcad23
    netsnmp_table_container_register(my_handler, table_info, &cb,
Packit fcad23
                                     cb.container, 1);
Packit fcad23
}
Packit fcad23
Packit fcad23
/************************************************************
Packit fcad23
 * ${i}_get_value
Packit fcad23
 *
Packit fcad23
 * This routine is called for get requests to copy the data
Packit fcad23
 * from the context to the varbind for the request. If the
Packit fcad23
 * context has been properly maintained, you don't need to
Packit fcad23
 * change in code in this fuction.
Packit fcad23
 */
Packit fcad23
int ${i}_get_value(
Packit fcad23
            netsnmp_request_info *request,
Packit fcad23
            netsnmp_index *item,
Packit fcad23
            netsnmp_table_request_info *table_info )
Packit fcad23
{
Packit fcad23
    netsnmp_variable_list *var = request->requestvb;
Packit fcad23
    ${i}_context *context = (${i}_context *)item;
Packit fcad23
Packit fcad23
    switch(table_info->colnum) {
Packit fcad23
Packit fcad23
        @foreach $c column@
Packit fcad23
        @if $c.readable@
Packit fcad23
            @eval $have_type = 0@
Packit fcad23
        case COLUMN_$c.uc:
Packit fcad23
            /** $c.syntax = $c.type */
Packit fcad23
            @if "$c.type" eq "ASN_OBJECT_ID"@
Packit fcad23
                @eval $have_type = 1@
Packit fcad23
            snmp_set_var_typed_value(var, $c.type,
Packit fcad23
                         (char*)&context->$c,
Packit fcad23
                         context->${c}_len );
Packit fcad23
            @end@
Packit fcad23
            @if "$c.type" eq "ASN_OCTET_STR"@
Packit fcad23
                @eval $have_type = 1@
Packit fcad23
            snmp_set_var_typed_value(var, $c.type,
Packit fcad23
                         (char*)&context->$c,
Packit fcad23
                         context->${c}_len );
Packit fcad23
            @end@
Packit fcad23
            @if $have_type == 0@
Packit fcad23
            snmp_set_var_typed_value(var, $c.type,
Packit fcad23
                         (char*)&context->$c,
Packit fcad23
                         sizeof(context->$c) );
Packit fcad23
            @end@
Packit fcad23
        break;
Packit fcad23
    
Packit fcad23
        @end@
Packit fcad23
        @end@
Packit fcad23
    default: /** We shouldn't get here */
Packit fcad23
        snmp_log(LOG_ERR, "unknown column in "
Packit fcad23
                 "${i}_get_value\n");
Packit fcad23
        return SNMP_ERR_GENERR;
Packit fcad23
    }
Packit fcad23
    return SNMP_ERR_NOERROR;
Packit fcad23
}
Packit fcad23
Packit fcad23
/************************************************************
Packit fcad23
 * ${i}_get_by_idx
Packit fcad23
 */
Packit fcad23
const ${i}_context *
Packit fcad23
${i}_get_by_idx(netsnmp_index * hdr)
Packit fcad23
{
Packit fcad23
    return (const ${i}_context *)
Packit fcad23
        CONTAINER_FIND(cb.container, hdr );
Packit fcad23
}
Packit fcad23
Packit fcad23
Packit fcad23
@end@