home *** CD-ROM | disk | FTP | other *** search
/ H4CK3R 16 / hacker16 / 16_HACKER16.ISO / linux / tpm-security-server-1.2.1.iso / archive / etc / snmp / mib2c.array-user.conf next >
Encoding:
Text File  |  2004-01-29  |  35.8 KB  |  1,279 lines

  1. ## -*- c -*-
  2. ##
  3. ## For documentation on the code generated by this configuration file,
  4. ## see the file agent/helpers/table_array.c.
  5. ##
  6. ######################################################################
  7. ## Do the .h file
  8. ## @perleval $vars{shortname} =~ s/([A-Z])[a-z]+/$1/g@
  9. ######################################################################
  10. @foreach $i table@
  11. @open ${i}.h@
  12. @eval $hack = "Id"
  13. /*
  14.  * Note: this file originally auto-generated by mib2c using
  15.  *        $Id: mib2c.array-user.conf,v 5.15.2.1 2003/02/27 05:59:41 rstory Exp $
  16.  *
  17.  * $$hack:$
  18.  *
  19.  * Yes, there is lots of code here that you might not use. But it is much
  20.  * easier to remove code than to add it!
  21.  */
  22. #ifndef $i.uc_H
  23. #define $i.uc_H
  24.  
  25. #ifdef __cplusplus
  26. extern "C" {
  27. #endif
  28.  
  29.     
  30. #include <net-snmp/net-snmp-config.h>
  31. #include <net-snmp/library/container.h>
  32. #include <net-snmp/agent/table_array.h>
  33.  
  34.     @eval $ext_index = 0@
  35.     @foreach $idx index@
  36.         @if "$idx" ne ""@
  37.         @eval $found = "external"@
  38.         @foreach $c column@
  39.             @if "$idx" eq "$c"@
  40.                @eval $found = "internal"@
  41.             @end@
  42.         @end@
  43.         /** Index $idx is $found */
  44.         @if "$found" eq "external"@
  45.            @eval $ext_index = 1@
  46.         @end@
  47.         @end@
  48.     @end@
  49.  
  50. typedef struct ${i}_context_s {
  51.     netsnmp_index index; /** THIS MUST BE FIRST!!! */
  52.  
  53.     /*************************************************************
  54.      * You can store data internally in this structure.
  55.      *
  56.      * TODO: You will probably have to fix a few types here...
  57.      */
  58.     @if $ext_index != 0@
  59.     /** TODO: add storage for external index(s)! */
  60.     @end@
  61.     @foreach $c column@
  62.         /** $c.syntax = $c.type */
  63.         @eval $have_type = 0@
  64.         @if "$c.type" eq "ASN_OCTET_STR"@
  65.             @eval $have_type = 1@
  66.             @eval $o_len = "65535"@
  67.             @if "$c.syntax" eq "DisplayString"@
  68.                 @eval $o_len = "255"@
  69.             @end@
  70.             @if "$c.syntax" eq "SnmpAdminString"@
  71.                 @eval $o_len = "255"@
  72.             @end@
  73.             unsigned char $c[$o_len];
  74.             long ${c}_len;
  75.         @end@
  76.         @if "$c.type" eq "ASN_OBJECT_ID"@
  77.             @eval $have_type = 1@
  78.             oid $c[MAX_OID_LEN];
  79.             long ${c}_len;
  80.         @end@
  81.         @if "$c.type" eq "ASN_UNSIGNED"@
  82.             @eval $have_type = 1@
  83.             unsigned long $c;
  84.         @end@
  85.         @if "$c.type" eq "ASN_TIMETICKS"@
  86.             @eval $have_type = 1@
  87.             unsigned long $c;
  88.         @end@
  89.         @if "$c.type" eq "ASN_IPADDRESS"@
  90.             @eval $have_type = 1@
  91.             unsigned long $c;
  92.         @end@
  93.         @if "$c.type" eq "ASN_UINTEGER"@
  94.             @eval $have_type = 1@
  95.             unsigned long $c;
  96.         @end@
  97.         @if "$c.type" eq "ASN_INTEGER"@
  98.             @eval $have_type = 1@
  99.             long $c;
  100.         @end@
  101.         @if "$c.type" eq "ASN_COUNTER"@
  102.             @eval $have_type = 1@
  103.             unsigned long $c;
  104.         @end@
  105.         @if $have_type == 0@
  106.     /** TODO: Is this type correct? */
  107.             long $c;
  108.         @end@
  109.  
  110.     @end@
  111.  
  112.     /*
  113.      * OR
  114.      *
  115.      * Keep a pointer to your data
  116.      */
  117.     void * data;
  118.  
  119.     /*
  120.      *add anything else you want here
  121.      */
  122.  
  123. } ${i}_context;
  124.  
  125. /*************************************************************
  126.  * function declarations
  127.  */
  128. void init_$i(void);
  129. void initialize_table_$i(void);
  130. const ${i}_context * ${i}_get_by_idx(netsnmp_index *);
  131. const ${i}_context * ${i}_get_by_idx_rs(netsnmp_index *,
  132.                                         int row_status);
  133. int ${i}_get_value(netsnmp_request_info *, netsnmp_index *, netsnmp_table_request_info *);
  134.  
  135.  
  136. /*************************************************************
  137.  * oid declarations
  138.  */
  139. extern oid ${i}_oid[];
  140. extern size_t ${i}_oid_len;
  141.  
  142. #define ${i}_TABLE_OID $i.commaoid
  143.     
  144. /*************************************************************
  145.  * column number definitions for table $i
  146.  */
  147. @eval $minv = 0xffffffff@
  148. @eval $maxv = 0@
  149. @foreach $c column@
  150. #define COLUMN_$c.uc $c.subid
  151. @if ! $c.noaccess@
  152. @eval $minv = min($minv, $c.subid)@
  153. @eval $maxv = max($maxv, $c.subid)@
  154. @end@
  155. @if "$c.syntax" eq "RowStatus"@
  156.    @eval $rs_name = "$c"@
  157. @end@
  158. @if "$c.syntax" eq "StorageType"@
  159.    @eval $st_name = "$c"@
  160. @end@
  161. @end@
  162. #define ${i}_COL_MIN $minv
  163. #define ${i}_COL_MAX $maxv
  164.  
  165. /* comment out the following line if you don't handle SET-REQUEST for $i */
  166. #define ${i}_SET_HANDLING
  167.  
  168. /* comment out the following line if you can't create new rows */
  169. #define ${i}_ROW_CREATION
  170.  
  171. /* comment out the following line if you don't want the secondary index */
  172. #define ${i}_IDX2
  173.  
  174. @if "$rs_name" ne ""@
  175. /* uncommend the following line if you allow modifications to an
  176.  * active row */
  177. /** define ${i}_CAN_MODIFY_ACTIVE_ROW */
  178.  
  179. @end@
  180. #ifdef ${i}_SET_HANDLING
  181.  
  182. int ${i}_extract_index( ${i}_context * ctx, netsnmp_index * hdr );
  183.  
  184. void ${i}_set_reserve1( netsnmp_request_group * );
  185. void ${i}_set_reserve2( netsnmp_request_group * );
  186. void ${i}_set_action( netsnmp_request_group * );
  187. void ${i}_set_commit( netsnmp_request_group * );
  188. void ${i}_set_free( netsnmp_request_group * );
  189. void ${i}_set_undo( netsnmp_request_group * );
  190.  
  191. ${i}_context * ${i}_duplicate_row( ${i}_context* );
  192. netsnmp_index * ${i}_delete_row( ${i}_context* );
  193.  
  194. @if "$rs_name" ne ""@
  195. int ${i}_can_activate(${i}_context *undo_ctx,
  196.                       ${i}_context *row_ctx,
  197.                       netsnmp_request_group * rg);
  198. int ${i}_can_deactivate(${i}_context *undo_ctx,
  199.                         ${i}_context *row_ctx,
  200.                         netsnmp_request_group * rg);
  201. @end@
  202. int ${i}_can_delete(${i}_context *undo_ctx,
  203.                     ${i}_context *row_ctx,
  204.                     netsnmp_request_group * rg);
  205.     
  206.     
  207. #ifdef ${i}_ROW_CREATION
  208. ${i}_context * ${i}_create_row( netsnmp_index* );
  209. #endif
  210. #endif
  211.  
  212. #ifdef ${i}_IDX2
  213. ${i}_context * ${i}_get( const char *name, int len );
  214. #endif
  215.  
  216. #ifdef __cplusplus
  217. };
  218. #endif
  219.  
  220. #endif /** $i.uc_H */
  221. @end@
  222. ######################################################################
  223. ## Do the .c file
  224. ######################################################################
  225. @foreach $i table@
  226. @open ${i}.c@
  227. @eval $hack = "Id"@
  228. /*
  229.  * Note: this file originally auto-generated by mib2c using
  230.  *       $Id: mib2c.array-user.conf,v 5.15.2.1 2003/02/27 05:59:41 rstory Exp $
  231.  *
  232.  * $$hack:$
  233.  *
  234.  *
  235.  * For help understanding NET-SNMP in general, please check the 
  236.  *     documentation and FAQ at:
  237.  *
  238.  *     http://www.net-snmp.org/
  239.  *
  240.  *
  241.  * For help understanding this code, the agent and how it processes
  242.  *     requests, please check the following references.
  243.  *
  244.  *     http://www.net-snmp.org/tutorial/
  245.  *
  246.  *
  247.  * You can also join the #net-snmp channel on irc.openprojects.net
  248.  *     and ask for help there.
  249.  *
  250.  *
  251.  * And if all else fails, send a detailed message to the developers
  252.  *     describing the problem you are having to:
  253.  *
  254.  *    net-snmp-coders@lists.sourceforge.net
  255.  *
  256.  *
  257.  * Yes, there is lots of code here that you might not use. But it is much
  258.  * easier to remove code than to add it!
  259.  */
  260. #include <net-snmp/net-snmp-config.h>
  261. #include <net-snmp/net-snmp-includes.h>
  262. #include <net-snmp/agent/net-snmp-agent-includes.h>
  263.  
  264. #include <net-snmp/library/snmp_assert.h>
  265.  
  266. #include "${i}.h"
  267.  
  268. static     netsnmp_handler_registration *my_handler = NULL;
  269. static     netsnmp_table_array_callbacks cb;
  270.  
  271. oid ${i}_oid[] = { ${i}_TABLE_OID };
  272. size_t ${i}_oid_len = OID_LENGTH(${i}_oid);
  273.  
  274.  
  275. #ifdef ${i}_IDX2
  276. /************************************************************
  277.  * keep binary tree to find context by name
  278.  */
  279. static int ${i}_cmp( const void *lhs, const void *rhs );
  280.  
  281. /************************************************************
  282.  * compare two context pointers here. Return -1 if lhs < rhs,
  283.  * 0 if lhs == rhs, and 1 if lhs > rhs.
  284.  */
  285. static int
  286. ${i}_cmp( const void *lhs, const void *rhs )
  287. {
  288.     ${i}_context *context_l =
  289.         (${i}_context *)lhs;
  290.     ${i}_context *context_r =
  291.         (${i}_context *)rhs;
  292.  
  293.     /*
  294.      * check primary key, then secondary. Add your own code if
  295.      * there are more than 2 indexes
  296.      */
  297.     int rc;
  298.  
  299.     /*
  300.      * TODO: implement compare. Remove this ifdef code and
  301.      * add your own code here.
  302.      */
  303. #ifdef TABLE_CONTAINER_TODO
  304.     snmp_log(LOG_ERR,
  305.              "${i}_compare not implemented! Container order undefined\n" );
  306.     return 0;
  307. #endif
  308.     
  309.     /*
  310.      * EXAMPLE:
  311.      *   
  312.      * rc = strcmp( context_l->xxName, context_r->xxName);
  313.      *
  314.      * if(rc)
  315.      *   return rc;
  316.      *
  317.      * TODO: fix secondary keys (or delete if there are none)
  318.      *
  319.      * if(context_l->yy < context_r->yy) 
  320.      *   return -1;
  321.      *
  322.      * return (context_l->yy == context_r->yy) ? 0 : 1;
  323.      */
  324. }
  325.  
  326. /************************************************************
  327.  * search tree
  328.  */
  329. /** TODO: set additional indexes as parameters */
  330. ${i}_context *
  331. ${i}_get( const char *name, int len )
  332. {
  333.     ${i}_context tmp;
  334.  
  335.     /** we should have a secondary index */
  336.     netsnmp_assert(cb.container->next != NULL);
  337.     
  338.     /*
  339.      * TODO: implement compare. Remove this ifdef code and
  340.      * add your own code here.
  341.      */
  342. #ifdef TABLE_CONTAINER_TODO
  343.     snmp_log(LOG_ERR, "${i}_get not implemented!\n" );
  344.     return NULL;
  345. #endif
  346.  
  347.     /*
  348.      * EXAMPLE:
  349.      *
  350.      * if(len > sizeof(tmp.xxName))
  351.      *   return NULL;
  352.      *
  353.      * strncpy( tmp.xxName, name, sizeof(tmp.xxName) );
  354.      * tmp.xxName_len = len;
  355.      *
  356.      * return CONTAINER_FIND(cb.container->next, &tmp);
  357.      */
  358. }
  359. #endif
  360.  
  361.  
  362. /************************************************************
  363.  * Initializes the $i module
  364.  */
  365. void
  366. init_$i(void)
  367. {
  368.     initialize_table_$i();
  369.  
  370.     /*
  371.      * TODO: perform any startup stuff here
  372.      */
  373. }
  374.  
  375. /************************************************************
  376.  * the *_row_copy routine
  377.  */
  378. static int ${i}_row_copy(${i}_context * dst,
  379.                          ${i}_context * src)
  380. {
  381.     if(!dst||!src)
  382.         return 1;
  383.         
  384.     /*
  385.      * copy index, if provided
  386.      */
  387.     if(dst->index.oids)
  388.         free(dst->index.oids);
  389.     if(snmp_clone_mem( (void*)&dst->index.oids, src->index.oids,
  390.                            src->index.len * sizeof(oid) )) {
  391.         dst->index.oids = NULL;
  392.         return 1;
  393.     }
  394.     dst->index.len = src->index.len;
  395.     
  396.  
  397.     /*
  398.      * copy components into the context structure
  399.      */
  400.     @if $ext_index != 0@
  401.     /** TODO: add code for external index(s)! */
  402.     @end@
  403.     @foreach $c column@
  404.     @eval $have_type = 0@
  405.     @if "$c.type" eq "ASN_OCTET_STR"@
  406.     @eval $have_type = 1@
  407.     memcpy( dst->$c, src->$c, src->${c}_len );
  408.     dst->${c}_len = src->${c}_len;
  409.     @end@
  410.     @if "$c.type" eq "ASN_OBJECT_ID"@
  411.     @eval $have_type = 1@
  412.     memcpy( src->$c, dst->$c, src->${c}_len );
  413.     dst->${c}_len = src->${c}_len;
  414.     @end@
  415.     @if $have_type == 0@
  416.     dst->$c = src->$c;
  417.     @end@
  418.  
  419.     @end@
  420.     return 0;
  421. }
  422.  
  423. #ifdef ${i}_SET_HANDLING
  424.  
  425. /*
  426.  * the *_extract_index routine
  427.  */
  428. int
  429. ${i}_extract_index( ${i}_context * ctx, netsnmp_index * hdr )
  430. {
  431.     /*
  432.      * temporary local storage for extracting oid index
  433.      */
  434.     @if $ext_index != 0@
  435.     /** TODO: add storage for external index(s)! */
  436.     @end@
  437.     @eval $first_idx = ""@
  438.     @foreach $idx index@
  439.         @if "$first_idx" eq ""@
  440.         @eval $first_idx = $idx@
  441.         @end@
  442.     netsnmp_variable_list var_$idx;
  443.     @end@
  444.     int err;
  445.  
  446.     /*
  447.      * copy index, if provided
  448.      */
  449.     if(hdr) {
  450.         netsnmp_assert(ctx->index.oids == NULL);
  451.         if(snmp_clone_mem( (void*)&ctx->index.oids, hdr->oids,
  452.                            hdr->len * sizeof(oid) )) {
  453.             return -1;
  454.         }
  455.         ctx->index.len = hdr->len;
  456.     }
  457.  
  458.     /**
  459.      * Create variable to hold each component of the index
  460.      */
  461.     @if $ext_index != 0@
  462.        /** TODO: add code for external index(s)! */
  463.     @end@
  464.     @foreach $idx index@
  465.        memset( &var_$idx, 0x00, sizeof(var_$idx) );
  466.        var_${idx}.type = $idx.type;
  467.        /** TODO: link this index to the next, or NULL for the last one */
  468. #ifdef TABLE_CONTAINER_TODO
  469.     snmp_log(LOG_ERR, "${i}_extract_index index list not implemented!\n" );
  470.     return 0;
  471. #else
  472.        var_$idx.next_variable = &var_XX;
  473. #endif
  474.  
  475.     @end@
  476.  
  477.     /*
  478.      * parse the oid into the individual components
  479.      */
  480.     err = parse_oid_indexes( hdr->oids, hdr->len, &var_$first_idx );
  481.     if (err == SNMP_ERR_NOERROR) {
  482.        /*
  483.         * copy components into the context structure
  484.         */
  485.        @foreach $idx index@
  486.           @eval $found = "external"@
  487.           @foreach $c column@
  488.               @if "$idx" eq "$c"@
  489.                  @eval $found = "internal"@
  490.               @end@
  491.           @end@
  492.           @if "$found" eq "external"@
  493.               /** skipping external index $idx */
  494.           @end@
  495.           @if "$found" eq "internal"@
  496.              @eval $have_type = 0@
  497.              @if "$idx.type" eq "ASN_OCTET_STR"@
  498.              @eval $have_type = 1@
  499.                 if(var_$idx.val_len > sizeof(ctx->$idx))
  500.                    err = -1;
  501.                 else
  502.                     memcpy( ctx->$idx, var_$idx.val.string, var_$idx.val_len );
  503.                 ctx->${idx}_len = var_$idx.val_len;
  504.              @end@
  505.              @if "$idx.type" eq "ASN_OBJECT_ID"@
  506.              @eval $have_type = 1@
  507.                 memcpy( ctx->$idx, var_$idx.val.string, var_$idx.val_len );
  508.                 ctx->$idx_len = var_$idx.val_len;
  509.              @end@
  510.              @if $have_type == 0@
  511.                 ctx->$idx = *var_$idx.val.integer;
  512.              @end@
  513.           @end@
  514.    
  515.        @end@
  516.    
  517.        @foreach $c index@
  518.            /*
  519.             * TODO: check index for valid values. For EXAMPLE:
  520.             *
  521.           @eval $have_check = 0@
  522.           @if "$c.type" eq "ASN_IPADDRESS"@
  523.               @eval $have_check = 1@
  524.               * if ( XXX_check_ip( *var_$c.val.integer ) ) {
  525.           @end@
  526.           @if "$c.type" eq "ASN_OBJECT_ID"@
  527.               @eval $have_check = 1@
  528.               * if ( XXX_check_oid( var_$c.val.objid, var_$c.val_len /
  529.                                     sizeof(oid) ) ) {
  530.           @end@
  531.           @if "$c.type" eq "ASN_OCTET_STR"@
  532.               @eval $have_check = 1@
  533.               * if ( XXX_check_value( var_$c.val.string, XXX ) ) {
  534.           @end@
  535.           @if $have_check != 1@
  536.               * if ( *var_$c.val.integer != XXX ) {
  537.           @end@
  538.           *    err = -1;
  539.           * }
  540.           */
  541.        @end@
  542.     }
  543.  
  544.     /*
  545.      * parsing may have allocated memory. free it.
  546.      */
  547.     snmp_reset_var_buffers( &var_$first_idx );
  548.  
  549.     return err;
  550. }
  551.  
  552. @if "$rs_name" ne ""@
  553. /************************************************************
  554.  * the *_can_activate routine is called
  555.  * when a row is changed to determine if all the values
  556.  * set are consistent with the row's rules for a row status
  557.  * of ACTIVE.
  558.  *
  559.  * return 1 if the row could be ACTIVE
  560.  * return 0 if the row is not ready for the ACTIVE state
  561.  */
  562. int ${i}_can_activate(${i}_context *undo_ctx,
  563.                       ${i}_context *row_ctx,
  564.                       netsnmp_request_group * rg)
  565. {
  566.     /*
  567.      * TODO: check for activation requirements here
  568.      */
  569.     return 1;
  570. }
  571.  
  572. /************************************************************
  573.  * the *_can_deactivate routine is called when a row that is
  574.  * currently ACTIVE is set to a state other than ACTIVE. If
  575.  * there are conditions in which a row should not be allowed
  576.  * to transition out of the ACTIVE state (such as the row being
  577.  * referred to by another row or table), check for them here.
  578.  *
  579.  * return 1 if the row can be set to a non-ACTIVE state
  580.  * return 0 if the row must remain in the ACTIVE state
  581.  */
  582. int ${i}_can_deactivate(${i}_context *undo_ctx,
  583.                         ${i}_context *row_ctx,
  584.                         netsnmp_request_group * rg)
  585. {
  586.     /*
  587.      * TODO: check for deactivation requirements here
  588.      */
  589.     return 1;
  590. }
  591.  
  592. @end@
  593. /************************************************************
  594.  * the *_can_delete routine is called to determine if a row
  595.  * can be deleted.
  596.  *
  597.  * return 1 if the row can be deleted
  598.  * return 0 if the row cannot be deleted
  599.  */
  600. int ${i}_can_delete(${i}_context *undo_ctx,
  601.                     ${i}_context *row_ctx,
  602.                     netsnmp_request_group * rg)
  603. {
  604. @if "$rs_name" ne ""@
  605.     /*
  606.      * probably shouldn't delete a row that we can't
  607.      * deactivate.
  608.      */
  609.     if(${i}_can_deactivate(undo_ctx,row_ctx,rg) != 1)
  610.         return 0;
  611. @end@
  612.     
  613.     /*
  614.      * TODO: check for other deletion requirements here
  615.      */
  616.     return 1;
  617. }
  618.  
  619. #ifdef ${i}_ROW_CREATION
  620. /************************************************************
  621.  * the *_create_row routine is called by the table handler
  622.  * to create a new row for a given index. If you need more
  623.  * information (such as column values) to make a decision
  624.  * on creating rows, you must create an initial row here
  625.  * (to hold the column values), and you can examine the
  626.  * situation in more detail in the *_set_reserve1 or later
  627.  * states of set processing. Simple check for a NULL undo_ctx
  628.  * in those states and do detailed creation checking there.
  629.  *
  630.  * returns a newly allocated ${i}_context
  631.  *   structure if the specified indexes are not illegal
  632.  * returns NULL for errors or illegal index values.
  633.  */
  634. ${i}_context *
  635. ${i}_create_row( netsnmp_index* hdr)
  636. {
  637.     ${i}_context * ctx =
  638.         SNMP_MALLOC_TYPEDEF(${i}_context);
  639.     if(!ctx)
  640.         return NULL;
  641.         
  642.     /*
  643.      * TODO: check indexes, if necessary.
  644.      */
  645.     if(${i}_extract_index( ctx, hdr )) {
  646.         free(ctx->index.oids);
  647.         free(ctx);
  648.         return NULL;
  649.     }
  650.  
  651.     /* netsnmp_mutex_init(ctx->lock);
  652.        netsnmp_mutex_lock(ctx->lock); */
  653.  
  654.     /*
  655.      * TODO: initialize any default values here. This is also
  656.      * first place you really should allocate any memory for
  657.      * yourself to use.  If you allocated memory earlier,
  658.      * make sure you free it for earlier error cases!
  659.      */
  660.     /**
  661.      @foreach $c column@
  662.      @if $c.settable@
  663.      ctx->$c = 0;
  664.      @end@
  665.      @end@
  666.     */
  667.  
  668.     return ctx;
  669. }
  670. #endif
  671.  
  672. /************************************************************
  673.  * the *_duplicate row routine
  674.  */
  675. ${i}_context *
  676. ${i}_duplicate_row( ${i}_context * row_ctx)
  677. {
  678.     ${i}_context * dup;
  679.  
  680.     if(!row_ctx)
  681.         return NULL;
  682.  
  683.     dup = SNMP_MALLOC_TYPEDEF(${i}_context);
  684.     if(!dup)
  685.         return NULL;
  686.         
  687.     if(${i}_row_copy(dup,row_ctx)) {
  688.         free(dup);
  689.         dup = NULL;
  690.     }
  691.  
  692.     return dup;
  693. }
  694.  
  695. /************************************************************
  696.  * the *_delete_row method is called to delete a row.
  697.  */
  698. netsnmp_index * ${i}_delete_row( ${i}_context * ctx )
  699. {
  700.   /* netsnmp_mutex_destroy(ctx->lock); */
  701.  
  702.     if(ctx->index.oids)
  703.         free(ctx->index.oids);
  704.  
  705.     /*
  706.      * TODO: release any memory you allocated here...
  707.      */
  708.  
  709.     /*
  710.      * release header
  711.      */
  712.     free( ctx );
  713.  
  714.     return NULL;
  715. }
  716.  
  717.  
  718. /************************************************************
  719.  * RESERVE is used to check the syntax of all the variables
  720.  * provided, that the values being set are sensible and consistent,
  721.  * and to allocate any resources required for performing the SET.
  722.  * After this stage, the expectation is that the set ought to
  723.  * succeed, though this is not guaranteed. (In fact, with the UCD
  724.  * agent, this is done in two passes - RESERVE1, and
  725.  * RESERVE2, to allow for dependancies between variables).
  726.  *
  727.  * BEFORE calling this routine, the agent will call duplicate_row
  728.  * to create a copy of the row (unless this is a new row; i.e.
  729.  * row_created == 1).
  730.  *
  731.  * next state -> SET_RESERVE2 || SET_FREE
  732.  */
  733. void ${i}_set_reserve1( netsnmp_request_group *rg )
  734. {
  735.     ${i}_context *row_ctx =
  736.             (${i}_context *)rg->existing_row;
  737.     ${i}_context *undo_ctx =
  738.             (${i}_context *)rg->undo_info;
  739.     netsnmp_variable_list *var;
  740.     netsnmp_request_group_item *current;
  741.     int rc;
  742.  
  743.     @if "$st_name" ne ""@
  744.         /*
  745.          * Block all attempts to modify a readOnly row
  746.          */
  747.     if( row_ctx && (row_ctx->$st_name == SNMP_STORAGE_READONLY) ) {
  748.         netsnmp_set_mode_request_error(MODE_SET_BEGIN, rg->list->ri,
  749.                                        SNMP_ERR_NOTWRITABLE);
  750.         return;
  751.     }
  752.     @end@
  753.  
  754.     /*
  755.      * TODO: loop through columns, check syntax and lengths. For
  756.      * columns which have no dependencies, you could also move
  757.      * the value/range checking here to attempt to catch error
  758.      * cases as early as possible.
  759.      */
  760.     for( current = rg->list; current; current = current->next ) {
  761.  
  762.         var = current->ri->requestvb;
  763.         rc = SNMP_ERR_NOERROR;
  764.  
  765.         switch(current->tri->colnum) {
  766.  
  767.         @foreach $c column@
  768.         @if $c.settable@
  769.         case COLUMN_$c.uc:
  770.             /** $c.syntax = $c.type */
  771.             rc = netsnmp_check_vb_type_and_size(var, $c.type,
  772.                                                 sizeof(row_ctx->$c));
  773.         break;
  774.  
  775.         @end@
  776.         @end@
  777.         default: /** We shouldn't get here */
  778.             rc = SNMP_ERR_GENERR;
  779.             snmp_log(LOG_ERR, "unknown column in "
  780.                      "${i}_set_reserve1\n");
  781.         }
  782.  
  783.         if (rc)
  784.            netsnmp_set_mode_request_error(MODE_SET_BEGIN, current->ri, rc );
  785.         rg->status = SNMP_MAX( rg->status, current->ri->status );
  786.     }
  787.  
  788.     /*
  789.      * done with all the columns. Could check row related
  790.      * requirements here.
  791.      */
  792. }
  793.  
  794. void ${i}_set_reserve2( netsnmp_request_group *rg )
  795. {
  796.     ${i}_context *row_ctx = (${i}_context *)rg->existing_row;
  797.     ${i}_context *undo_ctx = (${i}_context *)rg->undo_info;
  798.     netsnmp_request_group_item *current;
  799.     netsnmp_variable_list *var;
  800.     int rc;
  801.  
  802.     rg->rg_void = rg->list->ri;
  803.  
  804.     /*
  805.      * TODO: loop through columns, check for valid
  806.      * values and any range constraints.
  807.      */
  808.     for( current = rg->list; current; current = current->next ) {
  809.  
  810.         var = current->ri->requestvb;
  811.         rc = SNMP_ERR_NOERROR;
  812.  
  813.         switch(current->tri->colnum) {
  814.  
  815.         @foreach $c column@
  816.         @if $c.settable@
  817.         case COLUMN_$c.uc:
  818.             /** $c.syntax = $c.type */
  819.             @eval $have_check = 0@
  820.             @if "$c" eq "$st_name"@
  821.                 @eval $have_check = 1@
  822.                 rc = netsnmp_check_vb_storagetype(current->ri->requestvb,
  823.                                                   undo_ctx ?
  824.                                                   undo_ctx->$c:0);
  825.             @end@
  826.             @if "$c" eq "$rs_name"@
  827.                 @eval $have_check = 1@
  828.                 rc = netsnmp_check_vb_rowstatus(current->ri->requestvb,
  829.                                                 undo_ctx ?
  830.                                                 undo_ctx->$c:0);
  831.                 rg->rg_void = current->ri;
  832.             @end@
  833.             @if "$c.syntax" eq "TruthValue"@
  834.                 @eval $have_check = 1@
  835.                 rc = netsnmp_check_vb_truthvalue(current->ri->requestvb);
  836.             @end@
  837.             @if $have_check == 0@
  838.                     /*
  839.                      * TODO: routine to check valid values
  840.                      *
  841.                      * EXAMPLE:
  842.                      *
  843.                 @if "$c.type" eq "ASN_IPADDRESS"@
  844.                     @eval $have_check = 1@
  845.                     * if ( XXX_check_ip( *var->val.integer ) ) {
  846.                 @end@
  847.                 @if "$c.type" eq "ASN_OBJECT_ID"@
  848.                     @eval $have_check = 1@
  849.                     * if ( XXX_check_oid( var ) ) {
  850.                 @end@
  851.                 @if "$c.type" eq "ASN_OCTET_STR"@
  852.                     @eval $have_check = 1@
  853.                     * if ( XXX_check_value( var->val.string, XXX ) ) {
  854.                 @end@
  855.                 @if $have_check != 1@
  856.                     * if ( *var->val.integer != XXX ) {
  857.                 @end@
  858.                 *    rc = SNMP_ERR_INCONSISTENTVALUE;
  859.                 *    rc = SNMP_ERR_BADVALUE;
  860.                 * }
  861.                 */
  862.             @end@
  863.         break;
  864.  
  865.         @end@
  866.         @end@
  867.         default: /** We shouldn't get here */
  868.             netsnmp_assert(0); /** why wasn't this caught in reserve1? */
  869.         }
  870.  
  871.         if (rc)
  872.            netsnmp_set_mode_request_error(MODE_SET_BEGIN, current->ri, rc);
  873.     }
  874.  
  875.     /*
  876.      * done with all the columns. Could check row related
  877.      * requirements here.
  878.      */
  879. }
  880.  
  881. /************************************************************
  882.  * Assuming that the RESERVE phases were successful, the next
  883.  * stage is indicated by the action value ACTION. This is used
  884.  * to actually implement the set operation. However, this must
  885.  * either be done into temporary (persistent) storage, or the
  886.  * previous value stored similarly, in case any of the subsequent
  887.  * ACTION calls fail.
  888.  *
  889.  * In your case, changes should be made to row_ctx. A copy of
  890.  * the original row is in undo_ctx.
  891.  */
  892. void ${i}_set_action( netsnmp_request_group *rg )
  893. {
  894.     netsnmp_variable_list *var;
  895.     ${i}_context *row_ctx = (${i}_context *)rg->existing_row;
  896.     ${i}_context *undo_ctx = (${i}_context *)rg->undo_info;
  897.     netsnmp_request_group_item *current;
  898.  
  899.     @if "$rs_name" ne ""@
  900.     int            row_err = 0;
  901.     @end@
  902.  
  903.     /*
  904.      * TODO: loop through columns, copy varbind values
  905.      * to context structure for the row.
  906.      */
  907.     for( current = rg->list; current; current = current->next ) {
  908.  
  909.         var = current->ri->requestvb;
  910.  
  911.         switch(current->tri->colnum) {
  912.  
  913.         @foreach $c column@
  914.         @if $c.settable@
  915.         case COLUMN_$c.uc:
  916.             /** $c.syntax = $c.type */
  917.             @eval $have_type = 0@
  918.             @if "$c.type" eq "ASN_OCTET_STR"@
  919.             @eval $have_type = 1@
  920.             memcpy(row_ctx->$c,var->val.string,var->val_len);
  921.             row_ctx->${c}_len = var->val_len;
  922.             @end@
  923.             @if "$c.type" eq "ASN_OBJECT_ID"@
  924.             @eval $have_type = 1@
  925.             memcpy(row_ctx->$c,var->val.objid,var->val_len);
  926.             row_ctx->${c}_len = var->val_len;
  927.             @end@
  928.             @if $have_type == 0@
  929.             row_ctx->$c = *var->val.integer;
  930.             @end@
  931.         break;
  932.  
  933.         @end@
  934.         @end@
  935.         default: /** We shouldn't get here */
  936.             netsnmp_assert(0); /** why wasn't this caught in reserve1? */
  937.         }
  938.     }
  939.  
  940.     /*
  941.      * done with all the columns. Could check row related
  942.      * requirements here.
  943.      */
  944.     @if "$rs_name" ne ""@
  945. #ifndef ${i}_CAN_MODIFY_ACTIVE_ROW
  946.     if( undo_ctx && RS_IS_ACTIVE(undo_ctx->$rs_name) &&
  947.         row_ctx && RS_IS_ACTIVE(row_ctx->$rs_name) ) {
  948.             row_err = 1;
  949.     }
  950. #endif
  951.  
  952.     /*
  953.      * check activation/deactivation
  954.      */
  955.     row_err = netsnmp_table_array_check_row_status(&cb, rg,
  956.                                   row_ctx ? &row_ctx->$rs_name : NULL,
  957.                                   undo_ctx ? &undo_ctx->$rs_name : NULL);
  958.     if(row_err) {
  959.         netsnmp_set_mode_request_error(MODE_SET_BEGIN,
  960.                                        (netsnmp_request_info*)rg->rg_void,
  961.                                        row_err);
  962.         return;
  963.     }
  964.  
  965.     @end@
  966.     /*
  967.      * TODO: if you have dependencies on other tables, this would be
  968.      * a good place to check those, too.
  969.      */
  970. }
  971.  
  972. /************************************************************
  973.  * Only once the ACTION phase has completed successfully, can
  974.  * the final COMMIT phase be run. This is used to complete any
  975.  * writes that were done into temporary storage, and then release
  976.  * any allocated resources. Note that all the code in this phase
  977.  * should be "safe" code that cannot possibly fail (cue
  978.  * hysterical laughter). The whole intent of the ACTION/COMMIT
  979.  * division is that all of the fallible code should be done in
  980.  * the ACTION phase, so that it can be backed out if necessary.
  981.  *
  982.  * BEFORE calling this routine, the agent will update the
  983.  * container (inserting a row if row_created == 1, or removing
  984.  * the row if row_deleted == 1).
  985.  *
  986.  * AFTER calling this routine, the agent will delete the
  987.  * undo_info.
  988.  */
  989. void ${i}_set_commit( netsnmp_request_group *rg )
  990. {
  991.     netsnmp_variable_list *var;
  992.     ${i}_context *row_ctx = (${i}_context *)rg->existing_row;
  993.     ${i}_context *undo_ctx = (${i}_context *)rg->undo_info;
  994.     netsnmp_request_group_item *current;
  995.  
  996.     /*
  997.      * loop through columns
  998.      */
  999.     for( current = rg->list; current; current = current->next ) {
  1000.  
  1001.         var = current->ri->requestvb;
  1002.  
  1003.         switch(current->tri->colnum) {
  1004.  
  1005.         @foreach $c column@
  1006.         @if $c.settable@
  1007.         case COLUMN_$c.uc:
  1008.             /** $c.syntax = $c.type */
  1009.         break;
  1010.  
  1011.         @end@
  1012.         @end@
  1013.         default: /** We shouldn't get here */
  1014.             netsnmp_assert(0); /** why wasn't this caught in reserve1? */
  1015.         }
  1016.     }
  1017.  
  1018.     /*
  1019.      * done with all the columns. Could check row related
  1020.      * requirements here.
  1021.      */
  1022. }
  1023.  
  1024. /************************************************************
  1025.  * If either of the RESERVE calls fail, the write routines
  1026.  * are called again with the FREE action, to release any resources
  1027.  * that have been allocated. The agent will then return a failure
  1028.  * response to the requesting application.
  1029.  *
  1030.  * AFTER calling this routine, the agent will delete undo_info.
  1031.  */
  1032. void ${i}_set_free( netsnmp_request_group *rg )
  1033. {
  1034.     netsnmp_variable_list *var;
  1035.     ${i}_context *row_ctx = (${i}_context *)rg->existing_row;
  1036.     ${i}_context *undo_ctx = (${i}_context *)rg->undo_info;
  1037.     netsnmp_request_group_item *current;
  1038.  
  1039.     /*
  1040.      * loop through columns
  1041.      */
  1042.     for( current = rg->list; current; current = current->next ) {
  1043.  
  1044.         var = current->ri->requestvb;
  1045.  
  1046.         switch(current->tri->colnum) {
  1047.  
  1048.         @foreach $c column@
  1049.         @if $c.settable@
  1050.         case COLUMN_$c.uc:
  1051.             /** $c.syntax = $c.type */
  1052.         break;
  1053.  
  1054.         @end@
  1055.         @end@
  1056.         default: /** We shouldn't get here */
  1057.             /** should have been logged in reserve1 */
  1058.         }
  1059.     }
  1060.  
  1061.     /*
  1062.      * done with all the columns. Could check row related
  1063.      * requirements here.
  1064.      */
  1065. }
  1066.  
  1067. /************************************************************
  1068.  * If the ACTION phase does fail (for example due to an apparently
  1069.  * valid, but unacceptable value, or an unforeseen problem), then
  1070.  * the list of write routines are called again, with the UNDO
  1071.  * action. This requires the routine to reset the value that was
  1072.  * changed to its previous value (assuming it was actually changed),
  1073.  * and then to release any resources that had been allocated. As
  1074.  * with the FREE phase, the agent will then return an indication
  1075.  * of the error to the requesting application.
  1076.  *
  1077.  * BEFORE calling this routine, the agent will update the container
  1078.  * (remove any newly inserted row, re-insert any removed row).
  1079.  *
  1080.  * AFTER calling this routing, the agent will call row_copy
  1081.  * to restore the data in existing_row from the date in undo_info.
  1082.  * Then undo_info will be deleted (or existing row, if row_created
  1083.  * == 1).
  1084.  */
  1085. void ${i}_set_undo( netsnmp_request_group *rg )
  1086. {
  1087.     netsnmp_variable_list *var;
  1088.     ${i}_context *row_ctx = (${i}_context *)rg->existing_row;
  1089.     ${i}_context *undo_ctx = (${i}_context *)rg->undo_info;
  1090.     netsnmp_request_group_item *current;
  1091.  
  1092.     /*
  1093.      * loop through columns
  1094.      */
  1095.     for( current = rg->list; current; current = current->next ) {
  1096.  
  1097.         var = current->ri->requestvb;
  1098.  
  1099.         switch(current->tri->colnum) {
  1100.  
  1101.         @foreach $c column@
  1102.         @if $c.settable@
  1103.         case COLUMN_$c.uc:
  1104.             /** $c.syntax = $c.type */
  1105.         break;
  1106.  
  1107.         @end@
  1108.         @end@
  1109.         default: /** We shouldn't get here */
  1110.             netsnmp_assert(0); /** why wasn't this caught in reserve1? */
  1111.         }
  1112.     }
  1113.  
  1114.     /*
  1115.      * done with all the columns. Could check row related
  1116.      * requirements here.
  1117.      */
  1118. }
  1119.  
  1120. #endif /** ${i}_SET_HANDLING */
  1121.  
  1122.  
  1123. /************************************************************
  1124.  *
  1125.  * Initialize the $i table by defining its contents and how it's structured
  1126.  */
  1127. void
  1128. initialize_table_$i(void)
  1129. {
  1130.     netsnmp_table_registration_info *table_info;
  1131.  
  1132.     if(my_handler) {
  1133.         snmp_log(LOG_ERR, "initialize_table_${i}_handler called again\n");
  1134.         return;
  1135.     }
  1136.  
  1137.     memset(&cb, 0x00, sizeof(cb));
  1138.  
  1139.     /** create the table structure itself */
  1140.     table_info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info);
  1141.  
  1142.     /* if your table is read only, it's easiest to change the
  1143.        HANDLER_CAN_RWRITE definition below to HANDLER_CAN_RONLY */
  1144.     my_handler = netsnmp_create_handler_registration("$i",
  1145.                                              netsnmp_table_array_helper_handler,
  1146.                                              ${i}_oid,
  1147.                                              ${i}_oid_len,
  1148.                                              HANDLER_CAN_RWRITE);
  1149.             
  1150.     if (!my_handler || !table_info) {
  1151.         snmp_log(LOG_ERR, "malloc failed in "
  1152.                  "initialize_table_${i}_handler\n");
  1153.         return; /** mallocs failed */
  1154.     }
  1155.  
  1156.     /***************************************************
  1157.      * Setting up the table's definition
  1158.      */
  1159.     /*
  1160.      * TODO: add any external indexes here.
  1161.      */
  1162.     @if $ext_index != 0@
  1163.         /** TODO: add code for external index(s)! */
  1164.     @end@
  1165.  
  1166.     /*
  1167.      * internal indexes
  1168.      */
  1169.     @foreach $idx index@
  1170.         /** index: $idx */
  1171.         netsnmp_table_helper_add_index(table_info, $idx.type);
  1172.     @end@
  1173.  
  1174.     table_info->min_column = ${i}_COL_MIN;
  1175.     table_info->max_column = ${i}_COL_MAX;
  1176.  
  1177.     /***************************************************
  1178.      * registering the table with the master agent
  1179.      */
  1180.     cb.get_value = ${i}_get_value;
  1181.     cb.container = netsnmp_container_find("${i}_primary:"
  1182.                                           "${i}:"
  1183.                                           "table_container");
  1184. #ifdef ${i}_IDX2
  1185.     netsnmp_container_add_index(cb.container,
  1186.                                 netsnmp_container_find("${i}_secondary:"
  1187.                                                        "${i}:"
  1188.                                                        "table_container"));
  1189.     cb.container->next->compare = ${i}_cmp;
  1190. #endif
  1191. #ifdef ${i}_SET_HANDLING
  1192.     cb.can_set = 1;
  1193. #ifdef ${i}_ROW_CREATION
  1194.     cb.create_row = (UserRowMethod*)${i}_create_row;
  1195. #endif
  1196.     cb.duplicate_row = (UserRowMethod*)${i}_duplicate_row;
  1197.     cb.delete_row = (UserRowMethod*)${i}_delete_row;
  1198.     cb.row_copy = (Netsnmp_User_Row_Operation *)${i}_row_copy;
  1199.  
  1200. @if "$rs_name" ne ""@
  1201.     cb.can_activate = (Netsnmp_User_Row_Action *)${i}_can_activate;
  1202.     cb.can_deactivate = (Netsnmp_User_Row_Action *)${i}_can_deactivate;
  1203. @end@
  1204.     cb.can_delete = (Netsnmp_User_Row_Action *)${i}_can_delete;
  1205.  
  1206.     cb.set_reserve1 = ${i}_set_reserve1;
  1207.     cb.set_reserve2 = ${i}_set_reserve2;
  1208.     cb.set_action = ${i}_set_action;
  1209.     cb.set_commit = ${i}_set_commit;
  1210.     cb.set_free = ${i}_set_free;
  1211.     cb.set_undo = ${i}_set_undo;
  1212. #endif
  1213.     DEBUGMSGTL(("initialize_table_$i",
  1214.                 "Registering table $i "
  1215.                 "as a table array\n"));
  1216.     netsnmp_table_container_register(my_handler, table_info, &cb,
  1217.                                      cb.container, 1);
  1218. }
  1219.  
  1220. /************************************************************
  1221.  * ${i}_get_value
  1222.  */
  1223. int ${i}_get_value(
  1224.             netsnmp_request_info *request,
  1225.             netsnmp_index *item,
  1226.             netsnmp_table_request_info *table_info )
  1227. {
  1228.     netsnmp_variable_list *var = request->requestvb;
  1229.     ${i}_context *context = (${i}_context *)item;
  1230.  
  1231.     switch(table_info->colnum) {
  1232.  
  1233.         @foreach $c column@
  1234.             @eval $have_type = 0@
  1235.         case COLUMN_$c.uc:
  1236.             /** $c.syntax = $c.type */
  1237.             @if "$c.type" eq "ASN_OBJECT_ID"@
  1238.                 @eval $have_type = 1@
  1239.             snmp_set_var_typed_value(var, $c.type,
  1240.                          (char*)&context->$c,
  1241.                          context->${c}_len );
  1242.             @end@
  1243.             @if "$c.type" eq "ASN_OCTET_STR"@
  1244.                 @eval $have_type = 1@
  1245.             snmp_set_var_typed_value(var, $c.type,
  1246.                          (char*)&context->$c,
  1247.                          context->${c}_len );
  1248.             @end@
  1249.             @if $have_type == 0@
  1250.             snmp_set_var_typed_value(var, $c.type,
  1251.                          (char*)&context->$c,
  1252.                          sizeof(context->$c) );
  1253.             @end@
  1254.         break;
  1255.     
  1256.         @end@
  1257.     default: /** We shouldn't get here */
  1258.         snmp_log(LOG_ERR, "unknown column in "
  1259.                  "${i}_get_value\n");
  1260.         return SNMP_ERR_GENERR;
  1261.     }
  1262.     return SNMP_ERR_NOERROR;
  1263. }
  1264.  
  1265. /************************************************************
  1266.  * ${i}_get_by_idx
  1267.  */
  1268. const ${i}_context *
  1269. ${i}_get_by_idx(netsnmp_index * hdr)
  1270. {
  1271.     return (const ${i}_context *)
  1272.         CONTAINER_FIND(cb.container, hdr );
  1273. }
  1274.  
  1275.  
  1276. @end@
  1277. @end@
  1278. @end@
  1279.