~ubuntu-branches/ubuntu/trusty/net-snmp/trusty

« back to all changes in this revision

Viewing changes to local/mib2c.array-user.conf

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2004-09-13 12:06:21 UTC
  • Revision ID: james.westby@ubuntu.com-20040913120621-g952ntonlleihcvm
Tags: upstream-5.1.1
ImportĀ upstreamĀ versionĀ 5.1.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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.18.2.2 2004/02/09 18:21:47 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.18.2.2 2004/02/09 18:21:47 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-5/
 
245
 *
 
246
 *
 
247
 * You can also join the #net-snmp channel on irc.freenode.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 (assuming you want to sort on a name):
 
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, such as
 
372
     * populating the table with initial data.
 
373
     *
 
374
     * ${i}_context * new_row = create_row(index);
 
375
     * CONTAINER_INSERT(cb.container,new_row);
 
376
     */
 
377
}
 
378
 
 
379
/************************************************************
 
380
 * the *_row_copy routine
 
381
 */
 
382
static int ${i}_row_copy(${i}_context * dst,
 
383
                         ${i}_context * src)
 
384
{
 
385
    if(!dst||!src)
 
386
        return 1;
 
387
        
 
388
    /*
 
389
     * copy index, if provided
 
390
     */
 
391
    if(dst->index.oids)
 
392
        free(dst->index.oids);
 
393
    if(snmp_clone_mem( (void*)&dst->index.oids, src->index.oids,
 
394
                           src->index.len * sizeof(oid) )) {
 
395
        dst->index.oids = NULL;
 
396
        return 1;
 
397
    }
 
398
    dst->index.len = src->index.len;
 
399
    
 
400
 
 
401
    /*
 
402
     * copy components into the context structure
 
403
     */
 
404
    @if $ext_index != 0@
 
405
    /** TODO: add code for external index(s)! */
 
406
    @end@
 
407
    @foreach $c column@
 
408
    @eval $have_type = 0@
 
409
    @if "$c.type" eq "ASN_OCTET_STR"@
 
410
    @eval $have_type = 1@
 
411
    memcpy( dst->$c, src->$c, src->${c}_len );
 
412
    dst->${c}_len = src->${c}_len;
 
413
    @end@
 
414
    @if "$c.type" eq "ASN_OBJECT_ID"@
 
415
    @eval $have_type = 1@
 
416
    memcpy( src->$c, dst->$c, src->${c}_len );
 
417
    dst->${c}_len = src->${c}_len;
 
418
    @end@
 
419
    @if $have_type == 0@
 
420
    dst->$c = src->$c;
 
421
    @end@
 
422
 
 
423
    @end@
 
424
    return 0;
 
425
}
 
426
 
 
427
#ifdef ${i}_SET_HANDLING
 
428
 
 
429
/**
 
430
 * the *_extract_index routine
 
431
 *
 
432
 * This routine is called when a set request is received for an index
 
433
 * that was not found in the table container. Here, we parse the oid
 
434
 * in the the individual index components and copy those indexes to the
 
435
 * context. Then we make sure the indexes for the new row are valid.
 
436
 */
 
437
int
 
438
${i}_extract_index( ${i}_context * ctx, netsnmp_index * hdr )
 
439
{
 
440
    /*
 
441
     * temporary local storage for extracting oid index
 
442
     *
 
443
     * extract index uses varbinds (netsnmp_variable_list) to parse
 
444
     * the index OID into the individual components for each index part.
 
445
     */
 
446
    @if $ext_index != 0@
 
447
    /** TODO: add storage for external index(s)! */
 
448
    @end@
 
449
    @eval $first_idx = ""@
 
450
    @foreach $idx index@
 
451
        @if "$first_idx" eq ""@
 
452
        @eval $first_idx = $idx@
 
453
        @end@
 
454
    netsnmp_variable_list var_$idx;
 
455
    @end@
 
456
    int err;
 
457
 
 
458
    /*
 
459
     * copy index, if provided
 
460
     */
 
461
    if(hdr) {
 
462
        netsnmp_assert(ctx->index.oids == NULL);
 
463
        if(snmp_clone_mem( (void*)&ctx->index.oids, hdr->oids,
 
464
                           hdr->len * sizeof(oid) )) {
 
465
            return -1;
 
466
        }
 
467
        ctx->index.len = hdr->len;
 
468
    }
 
469
 
 
470
    /*
 
471
     * initialize variable that will hold each component of the index.
 
472
     * If there are multiple indexes for the table, the variable_lists
 
473
     * need to be linked together, in order.
 
474
     */
 
475
    @if $ext_index != 0@
 
476
       /** TODO: add code for external index(s)! */
 
477
    @end@
 
478
    @foreach $idx index@
 
479
       memset( &var_$idx, 0x00, sizeof(var_$idx) );
 
480
       var_${idx}.type = $idx.type; /* type hint for parse_oid_indexes */
 
481
       /** TODO: link this index to the next, or NULL for the last one */
 
482
#ifdef TABLE_CONTAINER_TODO
 
483
    snmp_log(LOG_ERR, "${i}_extract_index index list not implemented!\n" );
 
484
    return 0;
 
485
#else
 
486
       var_${idx}.next_variable = &var_XX;
 
487
#endif
 
488
 
 
489
    @end@
 
490
 
 
491
    /*
 
492
     * parse the oid into the individual index components
 
493
     */
 
494
    err = parse_oid_indexes( hdr->oids, hdr->len, &var_$first_idx );
 
495
    if (err == SNMP_ERR_NOERROR) {
 
496
       /*
 
497
        * copy index components into the context structure
 
498
        */
 
499
       @foreach $idx index@
 
500
          @eval $found = "external"@
 
501
          @foreach $c column@
 
502
              @if "$idx" eq "$c"@
 
503
                 @eval $found = "internal"@
 
504
              @end@
 
505
          @end@
 
506
          @if "$found" eq "external"@
 
507
              /** skipping external index $idx */
 
508
          @end@
 
509
          @if "$found" eq "internal"@
 
510
             @eval $have_type = 0@
 
511
             @if "$idx.type" eq "ASN_OCTET_STR"@
 
512
             @eval $have_type = 1@
 
513
                if(var_${idx}.val_len > sizeof(ctx->$idx))
 
514
                   err = -1;
 
515
                else
 
516
                    memcpy( ctx->$idx, var_${idx}.val.string, var_${idx}.val_len );
 
517
                ctx->${idx}_len = var_${idx}.val_len;
 
518
             @end@
 
519
             @if "$idx.type" eq "ASN_OBJECT_ID"@
 
520
             @eval $have_type = 1@
 
521
                memcpy( ctx->$idx, var_${idx}.val.string, var_${idx}.val_len );
 
522
                ctx->${idx}_len = var_${idx}.val_len;
 
523
             @end@
 
524
             @if $have_type == 0@
 
525
                ctx->$idx = *var_${idx}.val.integer;
 
526
             @end@
 
527
          @end@
 
528
   
 
529
       @end@
 
530
   
 
531
       @foreach $c index@
 
532
           /*
 
533
            * TODO: check index for valid values. For EXAMPLE:
 
534
            *
 
535
          @eval $have_check = 0@
 
536
          @if "$c.type" eq "ASN_IPADDRESS"@
 
537
              @eval $have_check = 1@
 
538
              * if ( XXX_check_ip( *var_${c}.val.integer ) ) {
 
539
          @end@
 
540
          @if "$c.type" eq "ASN_OBJECT_ID"@
 
541
              @eval $have_check = 1@
 
542
              * if ( XXX_check_oid( var_${c}.val.objid, var_${c}.val_len /
 
543
                                    sizeof(oid) ) ) {
 
544
          @end@
 
545
          @if "$c.type" eq "ASN_OCTET_STR"@
 
546
              @eval $have_check = 1@
 
547
              * if ( XXX_check_value( var_${c}.val.string, XXX ) ) {
 
548
          @end@
 
549
          @if $have_check != 1@
 
550
              * if ( *var_${c}.val.integer != XXX ) {
 
551
          @end@
 
552
          *    err = -1;
 
553
          * }
 
554
          */
 
555
       @end@
 
556
    }
 
557
 
 
558
    /*
 
559
     * parsing may have allocated memory. free it.
 
560
     */
 
561
    snmp_reset_var_buffers( &var_$first_idx );
 
562
 
 
563
    return err;
 
564
}
 
565
 
 
566
@if "$rs_name" ne ""@
 
567
/************************************************************
 
568
 * the *_can_activate routine is called
 
569
 * when a row is changed to determine if all the values
 
570
 * set are consistent with the row's rules for a row status
 
571
 * of ACTIVE.
 
572
 *
 
573
 * return 1 if the row could be ACTIVE
 
574
 * return 0 if the row is not ready for the ACTIVE state
 
575
 */
 
576
int ${i}_can_activate(${i}_context *undo_ctx,
 
577
                      ${i}_context *row_ctx,
 
578
                      netsnmp_request_group * rg)
 
579
{
 
580
    /*
 
581
     * TODO: check for activation requirements here
 
582
     */
 
583
 
 
584
 
 
585
    /*
 
586
     * be optimistic.
 
587
     */
 
588
    return 1;
 
589
}
 
590
 
 
591
/************************************************************
 
592
 * the *_can_deactivate routine is called when a row that is
 
593
 * currently ACTIVE is set to a state other than ACTIVE. If
 
594
 * there are conditions in which a row should not be allowed
 
595
 * to transition out of the ACTIVE state (such as the row being
 
596
 * referred to by another row or table), check for them here.
 
597
 *
 
598
 * return 1 if the row can be set to a non-ACTIVE state
 
599
 * return 0 if the row must remain in the ACTIVE state
 
600
 */
 
601
int ${i}_can_deactivate(${i}_context *undo_ctx,
 
602
                        ${i}_context *row_ctx,
 
603
                        netsnmp_request_group * rg)
 
604
{
 
605
    /*
 
606
     * TODO: check for deactivation requirements here
 
607
     */
 
608
    return 1;
 
609
}
 
610
 
 
611
@end@
 
612
/************************************************************
 
613
 * the *_can_delete routine is called to determine if a row
 
614
 * can be deleted.
 
615
 *
 
616
 * return 1 if the row can be deleted
 
617
 * return 0 if the row cannot be deleted
 
618
 */
 
619
int ${i}_can_delete(${i}_context *undo_ctx,
 
620
                    ${i}_context *row_ctx,
 
621
                    netsnmp_request_group * rg)
 
622
{
 
623
@if "$rs_name" ne ""@
 
624
    /*
 
625
     * probably shouldn't delete a row that we can't
 
626
     * deactivate.
 
627
     */
 
628
    if(${i}_can_deactivate(undo_ctx,row_ctx,rg) != 1)
 
629
        return 0;
 
630
@end@
 
631
    
 
632
    /*
 
633
     * TODO: check for other deletion requirements here
 
634
     */
 
635
    return 1;
 
636
}
 
637
 
 
638
#ifdef ${i}_ROW_CREATION
 
639
/************************************************************
 
640
 * the *_create_row routine is called by the table handler
 
641
 * to create a new row for a given index. If you need more
 
642
 * information (such as column values) to make a decision
 
643
 * on creating rows, you must create an initial row here
 
644
 * (to hold the column values), and you can examine the
 
645
 * situation in more detail in the *_set_reserve1 or later
 
646
 * states of set processing. Simple check for a NULL undo_ctx
 
647
 * in those states and do detailed creation checking there.
 
648
 *
 
649
 * returns a newly allocated ${i}_context
 
650
 *   structure if the specified indexes are not illegal
 
651
 * returns NULL for errors or illegal index values.
 
652
 */
 
653
${i}_context *
 
654
${i}_create_row( netsnmp_index* hdr)
 
655
{
 
656
    ${i}_context * ctx =
 
657
        SNMP_MALLOC_TYPEDEF(${i}_context);
 
658
    if(!ctx)
 
659
        return NULL;
 
660
        
 
661
    /*
 
662
     * TODO: check indexes, if necessary.
 
663
     */
 
664
    if(${i}_extract_index( ctx, hdr )) {
 
665
        free(ctx->index.oids);
 
666
        free(ctx);
 
667
        return NULL;
 
668
    }
 
669
 
 
670
    /* netsnmp_mutex_init(ctx->lock);
 
671
       netsnmp_mutex_lock(ctx->lock); */
 
672
 
 
673
    /*
 
674
     * TODO: initialize any default values here. This is also
 
675
     * first place you really should allocate any memory for
 
676
     * yourself to use.  If you allocated memory earlier,
 
677
     * make sure you free it for earlier error cases!
 
678
     */
 
679
    /**
 
680
     @foreach $c column@
 
681
     @if $c.settable@
 
682
     ctx->$c = 0;
 
683
     @end@
 
684
     @end@
 
685
    */
 
686
 
 
687
    return ctx;
 
688
}
 
689
#endif
 
690
 
 
691
/************************************************************
 
692
 * the *_duplicate row routine
 
693
 */
 
694
${i}_context *
 
695
${i}_duplicate_row( ${i}_context * row_ctx)
 
696
{
 
697
    ${i}_context * dup;
 
698
 
 
699
    if(!row_ctx)
 
700
        return NULL;
 
701
 
 
702
    dup = SNMP_MALLOC_TYPEDEF(${i}_context);
 
703
    if(!dup)
 
704
        return NULL;
 
705
        
 
706
    if(${i}_row_copy(dup,row_ctx)) {
 
707
        free(dup);
 
708
        dup = NULL;
 
709
    }
 
710
 
 
711
    return dup;
 
712
}
 
713
 
 
714
/************************************************************
 
715
 * the *_delete_row method is called to delete a row.
 
716
 */
 
717
netsnmp_index * ${i}_delete_row( ${i}_context * ctx )
 
718
{
 
719
  /* netsnmp_mutex_destroy(ctx->lock); */
 
720
 
 
721
    if(ctx->index.oids)
 
722
        free(ctx->index.oids);
 
723
 
 
724
    /*
 
725
     * TODO: release any memory you allocated here...
 
726
     */
 
727
 
 
728
    /*
 
729
     * release header
 
730
     */
 
731
    free( ctx );
 
732
 
 
733
    return NULL;
 
734
}
 
735
 
 
736
 
 
737
/************************************************************
 
738
 * RESERVE is used to check the syntax of all the variables
 
739
 * provided, that the values being set are sensible and consistent,
 
740
 * and to allocate any resources required for performing the SET.
 
741
 * After this stage, the expectation is that the set ought to
 
742
 * succeed, though this is not guaranteed. (In fact, with the UCD
 
743
 * agent, this is done in two passes - RESERVE1, and
 
744
 * RESERVE2, to allow for dependancies between variables).
 
745
 *
 
746
 * BEFORE calling this routine, the agent will call duplicate_row
 
747
 * to create a copy of the row (unless this is a new row; i.e.
 
748
 * row_created == 1).
 
749
 *
 
750
 * next state -> SET_RESERVE2 || SET_FREE
 
751
 */
 
752
void ${i}_set_reserve1( netsnmp_request_group *rg )
 
753
{
 
754
    ${i}_context *row_ctx =
 
755
            (${i}_context *)rg->existing_row;
 
756
    ${i}_context *undo_ctx =
 
757
            (${i}_context *)rg->undo_info;
 
758
    netsnmp_variable_list *var;
 
759
    netsnmp_request_group_item *current;
 
760
    int rc;
 
761
 
 
762
    @if "$st_name" ne ""@
 
763
        /*
 
764
         * Block all attempts to modify a readOnly row
 
765
         */
 
766
    if( row_ctx && (row_ctx->$st_name == SNMP_STORAGE_READONLY) ) {
 
767
        netsnmp_set_mode_request_error(MODE_SET_BEGIN, rg->list->ri,
 
768
                                       SNMP_ERR_NOTWRITABLE);
 
769
        return;
 
770
    }
 
771
    @end@
 
772
 
 
773
    /*
 
774
     * TODO: loop through columns, check syntax and lengths. For
 
775
     * columns which have no dependencies, you could also move
 
776
     * the value/range checking here to attempt to catch error
 
777
     * cases as early as possible.
 
778
     */
 
779
    for( current = rg->list; current; current = current->next ) {
 
780
 
 
781
        var = current->ri->requestvb;
 
782
        rc = SNMP_ERR_NOERROR;
 
783
 
 
784
        switch(current->tri->colnum) {
 
785
 
 
786
        @foreach $c column@
 
787
        @if $c.settable@
 
788
        case COLUMN_$c.uc:
 
789
            /** $c.syntax = $c.type */
 
790
            rc = netsnmp_check_vb_type_and_size(var, $c.type,
 
791
                                                sizeof(row_ctx->$c));
 
792
        break;
 
793
 
 
794
        @end@
 
795
        @end@
 
796
        default: /** We shouldn't get here */
 
797
            rc = SNMP_ERR_GENERR;
 
798
            snmp_log(LOG_ERR, "unknown column in "
 
799
                     "${i}_set_reserve1\n");
 
800
        }
 
801
 
 
802
        if (rc)
 
803
           netsnmp_set_mode_request_error(MODE_SET_BEGIN, current->ri, rc );
 
804
        rg->status = SNMP_MAX( rg->status, current->ri->status );
 
805
    }
 
806
 
 
807
    /*
 
808
     * done with all the columns. Could check row related
 
809
     * requirements here.
 
810
     */
 
811
}
 
812
 
 
813
void ${i}_set_reserve2( netsnmp_request_group *rg )
 
814
{
 
815
    ${i}_context *row_ctx = (${i}_context *)rg->existing_row;
 
816
    ${i}_context *undo_ctx = (${i}_context *)rg->undo_info;
 
817
    netsnmp_request_group_item *current;
 
818
    netsnmp_variable_list *var;
 
819
    int rc;
 
820
 
 
821
    rg->rg_void = rg->list->ri;
 
822
 
 
823
    /*
 
824
     * TODO: loop through columns, check for valid
 
825
     * values and any range constraints.
 
826
     */
 
827
    for( current = rg->list; current; current = current->next ) {
 
828
 
 
829
        var = current->ri->requestvb;
 
830
        rc = SNMP_ERR_NOERROR;
 
831
 
 
832
        switch(current->tri->colnum) {
 
833
 
 
834
        @foreach $c column@
 
835
        @if $c.settable@
 
836
        case COLUMN_$c.uc:
 
837
            /** $c.syntax = $c.type */
 
838
            @eval $have_check = 0@
 
839
            @if "$c" eq "$st_name"@
 
840
                @eval $have_check = 1@
 
841
                rc = netsnmp_check_vb_storagetype(current->ri->requestvb,
 
842
                                                  undo_ctx ?
 
843
                                                  undo_ctx->$c:0);
 
844
            @end@
 
845
            @if "$c" eq "$rs_name"@
 
846
                @eval $have_check = 1@
 
847
                rc = netsnmp_check_vb_rowstatus(current->ri->requestvb,
 
848
                                                undo_ctx ?
 
849
                                                undo_ctx->$c:0);
 
850
                rg->rg_void = current->ri;
 
851
            @end@
 
852
            @if "$c.syntax" eq "TruthValue"@
 
853
                @eval $have_check = 1@
 
854
                rc = netsnmp_check_vb_truthvalue(current->ri->requestvb);
 
855
            @end@
 
856
            @if $have_check == 0@
 
857
                    /*
 
858
                     * TODO: routine to check valid values
 
859
                     *
 
860
                     * EXAMPLE:
 
861
                     *
 
862
                @if "$c.type" eq "ASN_IPADDRESS"@
 
863
                    @eval $have_check = 1@
 
864
                    * if ( XXX_check_ip( *var->val.integer ) ) {
 
865
                @end@
 
866
                @if "$c.type" eq "ASN_OBJECT_ID"@
 
867
                    @eval $have_check = 1@
 
868
                    * if ( XXX_check_oid( var ) ) {
 
869
                @end@
 
870
                @if "$c.type" eq "ASN_OCTET_STR"@
 
871
                    @eval $have_check = 1@
 
872
                    * if ( XXX_check_value( var->val.string, XXX ) ) {
 
873
                @end@
 
874
                @if $have_check != 1@
 
875
                    * if ( *var->val.integer != XXX ) {
 
876
                @end@
 
877
                *    rc = SNMP_ERR_INCONSISTENTVALUE;
 
878
                *    rc = SNMP_ERR_BADVALUE;
 
879
                * }
 
880
                */
 
881
            @end@
 
882
        break;
 
883
 
 
884
        @end@
 
885
        @end@
 
886
        default: /** We shouldn't get here */
 
887
            netsnmp_assert(0); /** why wasn't this caught in reserve1? */
 
888
        }
 
889
 
 
890
        if (rc)
 
891
           netsnmp_set_mode_request_error(MODE_SET_BEGIN, current->ri, rc);
 
892
    }
 
893
 
 
894
    /*
 
895
     * done with all the columns. Could check row related
 
896
     * requirements here.
 
897
     */
 
898
}
 
899
 
 
900
/************************************************************
 
901
 * Assuming that the RESERVE phases were successful, the next
 
902
 * stage is indicated by the action value ACTION. This is used
 
903
 * to actually implement the set operation. However, this must
 
904
 * either be done into temporary (persistent) storage, or the
 
905
 * previous value stored similarly, in case any of the subsequent
 
906
 * ACTION calls fail.
 
907
 *
 
908
 * In your case, changes should be made to row_ctx. A copy of
 
909
 * the original row is in undo_ctx.
 
910
 */
 
911
void ${i}_set_action( netsnmp_request_group *rg )
 
912
{
 
913
    netsnmp_variable_list *var;
 
914
    ${i}_context *row_ctx = (${i}_context *)rg->existing_row;
 
915
    ${i}_context *undo_ctx = (${i}_context *)rg->undo_info;
 
916
    netsnmp_request_group_item *current;
 
917
 
 
918
    @if "$rs_name" ne ""@
 
919
    int            row_err = 0;
 
920
    @end@
 
921
 
 
922
    /*
 
923
     * TODO: loop through columns, copy varbind values
 
924
     * to context structure for the row.
 
925
     */
 
926
    for( current = rg->list; current; current = current->next ) {
 
927
 
 
928
        var = current->ri->requestvb;
 
929
 
 
930
        switch(current->tri->colnum) {
 
931
 
 
932
        @foreach $c column@
 
933
        @if $c.settable@
 
934
        case COLUMN_$c.uc:
 
935
            /** $c.syntax = $c.type */
 
936
            @eval $have_type = 0@
 
937
            @if "$c.type" eq "ASN_OCTET_STR"@
 
938
            @eval $have_type = 1@
 
939
            memcpy(row_ctx->$c,var->val.string,var->val_len);
 
940
            row_ctx->${c}_len = var->val_len;
 
941
            @end@
 
942
            @if "$c.type" eq "ASN_OBJECT_ID"@
 
943
            @eval $have_type = 1@
 
944
            memcpy(row_ctx->$c,var->val.objid,var->val_len);
 
945
            row_ctx->${c}_len = var->val_len;
 
946
            @end@
 
947
            @if $have_type == 0@
 
948
            row_ctx->$c = *var->val.integer;
 
949
            @end@
 
950
        break;
 
951
 
 
952
        @end@
 
953
        @end@
 
954
        default: /** We shouldn't get here */
 
955
            netsnmp_assert(0); /** why wasn't this caught in reserve1? */
 
956
        }
 
957
    }
 
958
 
 
959
    /*
 
960
     * done with all the columns. Could check row related
 
961
     * requirements here.
 
962
     */
 
963
    @if "$rs_name" ne ""@
 
964
#ifndef ${i}_CAN_MODIFY_ACTIVE_ROW
 
965
    if( undo_ctx && RS_IS_ACTIVE(undo_ctx->$rs_name) &&
 
966
        row_ctx && RS_IS_ACTIVE(row_ctx->$rs_name) ) {
 
967
            row_err = 1;
 
968
    }
 
969
#endif
 
970
 
 
971
    /*
 
972
     * check activation/deactivation
 
973
     */
 
974
    row_err = netsnmp_table_array_check_row_status(&cb, rg,
 
975
                                  row_ctx ? &row_ctx->$rs_name : NULL,
 
976
                                  undo_ctx ? &undo_ctx->$rs_name : NULL);
 
977
    if(row_err) {
 
978
        netsnmp_set_mode_request_error(MODE_SET_BEGIN,
 
979
                                       (netsnmp_request_info*)rg->rg_void,
 
980
                                       row_err);
 
981
        return;
 
982
    }
 
983
 
 
984
    @end@
 
985
    /*
 
986
     * TODO: if you have dependencies on other tables, this would be
 
987
     * a good place to check those, too.
 
988
     */
 
989
}
 
990
 
 
991
/************************************************************
 
992
 * Only once the ACTION phase has completed successfully, can
 
993
 * the final COMMIT phase be run. This is used to complete any
 
994
 * writes that were done into temporary storage, and then release
 
995
 * any allocated resources. Note that all the code in this phase
 
996
 * should be "safe" code that cannot possibly fail (cue
 
997
 * hysterical laughter). The whole intent of the ACTION/COMMIT
 
998
 * division is that all of the fallible code should be done in
 
999
 * the ACTION phase, so that it can be backed out if necessary.
 
1000
 *
 
1001
 * BEFORE calling this routine, the agent will update the
 
1002
 * container (inserting a row if row_created == 1, or removing
 
1003
 * the row if row_deleted == 1).
 
1004
 *
 
1005
 * AFTER calling this routine, the agent will delete the
 
1006
 * undo_info.
 
1007
 */
 
1008
void ${i}_set_commit( netsnmp_request_group *rg )
 
1009
{
 
1010
    netsnmp_variable_list *var;
 
1011
    ${i}_context *row_ctx = (${i}_context *)rg->existing_row;
 
1012
    ${i}_context *undo_ctx = (${i}_context *)rg->undo_info;
 
1013
    netsnmp_request_group_item *current;
 
1014
 
 
1015
    /*
 
1016
     * loop through columns
 
1017
     */
 
1018
    for( current = rg->list; current; current = current->next ) {
 
1019
 
 
1020
        var = current->ri->requestvb;
 
1021
 
 
1022
        switch(current->tri->colnum) {
 
1023
 
 
1024
        @foreach $c column@
 
1025
        @if $c.settable@
 
1026
        case COLUMN_$c.uc:
 
1027
            /** $c.syntax = $c.type */
 
1028
        break;
 
1029
 
 
1030
        @end@
 
1031
        @end@
 
1032
        default: /** We shouldn't get here */
 
1033
            netsnmp_assert(0); /** why wasn't this caught in reserve1? */
 
1034
        }
 
1035
    }
 
1036
 
 
1037
    /*
 
1038
     * done with all the columns. Could check row related
 
1039
     * requirements here.
 
1040
     */
 
1041
}
 
1042
 
 
1043
/************************************************************
 
1044
 * If either of the RESERVE calls fail, the write routines
 
1045
 * are called again with the FREE action, to release any resources
 
1046
 * that have been allocated. The agent will then return a failure
 
1047
 * response to the requesting application.
 
1048
 *
 
1049
 * AFTER calling this routine, the agent will delete undo_info.
 
1050
 */
 
1051
void ${i}_set_free( netsnmp_request_group *rg )
 
1052
{
 
1053
    netsnmp_variable_list *var;
 
1054
    ${i}_context *row_ctx = (${i}_context *)rg->existing_row;
 
1055
    ${i}_context *undo_ctx = (${i}_context *)rg->undo_info;
 
1056
    netsnmp_request_group_item *current;
 
1057
 
 
1058
    /*
 
1059
     * loop through columns
 
1060
     */
 
1061
    for( current = rg->list; current; current = current->next ) {
 
1062
 
 
1063
        var = current->ri->requestvb;
 
1064
 
 
1065
        switch(current->tri->colnum) {
 
1066
 
 
1067
        @foreach $c column@
 
1068
        @if $c.settable@
 
1069
        case COLUMN_$c.uc:
 
1070
            /** $c.syntax = $c.type */
 
1071
        break;
 
1072
 
 
1073
        @end@
 
1074
        @end@
 
1075
        default: /** We shouldn't get here */
 
1076
            /** should have been logged in reserve1 */
 
1077
        }
 
1078
    }
 
1079
 
 
1080
    /*
 
1081
     * done with all the columns. Could check row related
 
1082
     * requirements here.
 
1083
     */
 
1084
}
 
1085
 
 
1086
/************************************************************
 
1087
 * If the ACTION phase does fail (for example due to an apparently
 
1088
 * valid, but unacceptable value, or an unforeseen problem), then
 
1089
 * the list of write routines are called again, with the UNDO
 
1090
 * action. This requires the routine to reset the value that was
 
1091
 * changed to its previous value (assuming it was actually changed),
 
1092
 * and then to release any resources that had been allocated. As
 
1093
 * with the FREE phase, the agent will then return an indication
 
1094
 * of the error to the requesting application.
 
1095
 *
 
1096
 * BEFORE calling this routine, the agent will update the container
 
1097
 * (remove any newly inserted row, re-insert any removed row).
 
1098
 *
 
1099
 * AFTER calling this routing, the agent will call row_copy
 
1100
 * to restore the data in existing_row from the date in undo_info.
 
1101
 * Then undo_info will be deleted (or existing row, if row_created
 
1102
 * == 1).
 
1103
 */
 
1104
void ${i}_set_undo( netsnmp_request_group *rg )
 
1105
{
 
1106
    netsnmp_variable_list *var;
 
1107
    ${i}_context *row_ctx = (${i}_context *)rg->existing_row;
 
1108
    ${i}_context *undo_ctx = (${i}_context *)rg->undo_info;
 
1109
    netsnmp_request_group_item *current;
 
1110
 
 
1111
    /*
 
1112
     * loop through columns
 
1113
     */
 
1114
    for( current = rg->list; current; current = current->next ) {
 
1115
 
 
1116
        var = current->ri->requestvb;
 
1117
 
 
1118
        switch(current->tri->colnum) {
 
1119
 
 
1120
        @foreach $c column@
 
1121
        @if $c.settable@
 
1122
        case COLUMN_$c.uc:
 
1123
            /** $c.syntax = $c.type */
 
1124
        break;
 
1125
 
 
1126
        @end@
 
1127
        @end@
 
1128
        default: /** We shouldn't get here */
 
1129
            netsnmp_assert(0); /** why wasn't this caught in reserve1? */
 
1130
        }
 
1131
    }
 
1132
 
 
1133
    /*
 
1134
     * done with all the columns. Could check row related
 
1135
     * requirements here.
 
1136
     */
 
1137
}
 
1138
 
 
1139
#endif /** ${i}_SET_HANDLING */
 
1140
 
 
1141
 
 
1142
/************************************************************
 
1143
 *
 
1144
 * Initialize the $i table by defining its contents and how it's structured
 
1145
 */
 
1146
void
 
1147
initialize_table_$i(void)
 
1148
{
 
1149
    netsnmp_table_registration_info *table_info;
 
1150
 
 
1151
    if(my_handler) {
 
1152
        snmp_log(LOG_ERR, "initialize_table_${i}_handler called again\n");
 
1153
        return;
 
1154
    }
 
1155
 
 
1156
    memset(&cb, 0x00, sizeof(cb));
 
1157
 
 
1158
    /** create the table structure itself */
 
1159
    table_info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info);
 
1160
 
 
1161
    /* if your table is read only, it's easiest to change the
 
1162
       HANDLER_CAN_RWRITE definition below to HANDLER_CAN_RONLY */
 
1163
    my_handler = netsnmp_create_handler_registration("$i",
 
1164
                                             netsnmp_table_array_helper_handler,
 
1165
                                             ${i}_oid,
 
1166
                                             ${i}_oid_len,
 
1167
                                             HANDLER_CAN_RWRITE);
 
1168
            
 
1169
    if (!my_handler || !table_info) {
 
1170
        snmp_log(LOG_ERR, "malloc failed in "
 
1171
                 "initialize_table_${i}_handler\n");
 
1172
        return; /** mallocs failed */
 
1173
    }
 
1174
 
 
1175
    /***************************************************
 
1176
     * Setting up the table's definition
 
1177
     */
 
1178
    /*
 
1179
     * TODO: add any external indexes here.
 
1180
     */
 
1181
    @if $ext_index != 0@
 
1182
        /** TODO: add code for external index(s)! */
 
1183
    @end@
 
1184
 
 
1185
    /*
 
1186
     * internal indexes
 
1187
     */
 
1188
    @foreach $idx index@
 
1189
        /** index: $idx */
 
1190
        netsnmp_table_helper_add_index(table_info, $idx.type);
 
1191
    @end@
 
1192
 
 
1193
    table_info->min_column = ${i}_COL_MIN;
 
1194
    table_info->max_column = ${i}_COL_MAX;
 
1195
 
 
1196
    /***************************************************
 
1197
     * registering the table with the master agent
 
1198
     */
 
1199
    cb.get_value = ${i}_get_value;
 
1200
    cb.container = netsnmp_container_find("${i}_primary:"
 
1201
                                          "${i}:"
 
1202
                                          "table_container");
 
1203
#ifdef ${i}_IDX2
 
1204
    netsnmp_container_add_index(cb.container,
 
1205
                                netsnmp_container_find("${i}_secondary:"
 
1206
                                                       "${i}:"
 
1207
                                                       "table_container"));
 
1208
    cb.container->next->compare = ${i}_cmp;
 
1209
#endif
 
1210
#ifdef ${i}_SET_HANDLING
 
1211
    cb.can_set = 1;
 
1212
#ifdef ${i}_ROW_CREATION
 
1213
    cb.create_row = (UserRowMethod*)${i}_create_row;
 
1214
#endif
 
1215
    cb.duplicate_row = (UserRowMethod*)${i}_duplicate_row;
 
1216
    cb.delete_row = (UserRowMethod*)${i}_delete_row;
 
1217
    cb.row_copy = (Netsnmp_User_Row_Operation *)${i}_row_copy;
 
1218
 
 
1219
@if "$rs_name" ne ""@
 
1220
    cb.can_activate = (Netsnmp_User_Row_Action *)${i}_can_activate;
 
1221
    cb.can_deactivate = (Netsnmp_User_Row_Action *)${i}_can_deactivate;
 
1222
@end@
 
1223
    cb.can_delete = (Netsnmp_User_Row_Action *)${i}_can_delete;
 
1224
 
 
1225
    cb.set_reserve1 = ${i}_set_reserve1;
 
1226
    cb.set_reserve2 = ${i}_set_reserve2;
 
1227
    cb.set_action = ${i}_set_action;
 
1228
    cb.set_commit = ${i}_set_commit;
 
1229
    cb.set_free = ${i}_set_free;
 
1230
    cb.set_undo = ${i}_set_undo;
 
1231
#endif
 
1232
    DEBUGMSGTL(("initialize_table_$i",
 
1233
                "Registering table $i "
 
1234
                "as a table array\n"));
 
1235
    netsnmp_table_container_register(my_handler, table_info, &cb,
 
1236
                                     cb.container, 1);
 
1237
}
 
1238
 
 
1239
/************************************************************
 
1240
 * ${i}_get_value
 
1241
 *
 
1242
 * This routine is called for get requests to copy the data
 
1243
 * from the context to the varbind for the request. If the
 
1244
 * context has been properly maintained, you don't need to
 
1245
 * change in code in this fuction.
 
1246
 */
 
1247
int ${i}_get_value(
 
1248
            netsnmp_request_info *request,
 
1249
            netsnmp_index *item,
 
1250
            netsnmp_table_request_info *table_info )
 
1251
{
 
1252
    netsnmp_variable_list *var = request->requestvb;
 
1253
    ${i}_context *context = (${i}_context *)item;
 
1254
 
 
1255
    switch(table_info->colnum) {
 
1256
 
 
1257
        @foreach $c column@
 
1258
            @eval $have_type = 0@
 
1259
        case COLUMN_$c.uc:
 
1260
            /** $c.syntax = $c.type */
 
1261
            @if "$c.type" eq "ASN_OBJECT_ID"@
 
1262
                @eval $have_type = 1@
 
1263
            snmp_set_var_typed_value(var, $c.type,
 
1264
                         (char*)&context->$c,
 
1265
                         context->${c}_len );
 
1266
            @end@
 
1267
            @if "$c.type" eq "ASN_OCTET_STR"@
 
1268
                @eval $have_type = 1@
 
1269
            snmp_set_var_typed_value(var, $c.type,
 
1270
                         (char*)&context->$c,
 
1271
                         context->${c}_len );
 
1272
            @end@
 
1273
            @if $have_type == 0@
 
1274
            snmp_set_var_typed_value(var, $c.type,
 
1275
                         (char*)&context->$c,
 
1276
                         sizeof(context->$c) );
 
1277
            @end@
 
1278
        break;
 
1279
    
 
1280
        @end@
 
1281
    default: /** We shouldn't get here */
 
1282
        snmp_log(LOG_ERR, "unknown column in "
 
1283
                 "${i}_get_value\n");
 
1284
        return SNMP_ERR_GENERR;
 
1285
    }
 
1286
    return SNMP_ERR_NOERROR;
 
1287
}
 
1288
 
 
1289
/************************************************************
 
1290
 * ${i}_get_by_idx
 
1291
 */
 
1292
const ${i}_context *
 
1293
${i}_get_by_idx(netsnmp_index * hdr)
 
1294
{
 
1295
    return (const ${i}_context *)
 
1296
        CONTAINER_FIND(cb.container, hdr );
 
1297
}
 
1298
 
 
1299
 
 
1300
@end@
 
1301
@end@
 
1302
@end@