Coverage Report

Created: 2026-03-15 06:41

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/net-snmp/agent/helpers/instance.c
Line
Count
Source
1
/* Portions of this file are subject to the following copyright(s).  See
2
 * the Net-SNMP's COPYING file for more details and other copyrights
3
 * that may apply:
4
 */
5
/*
6
 * Portions of this file are copyrighted by:
7
 * Copyright © 2003 Sun Microsystems, Inc. All rights reserved.
8
 * Use is subject to license terms specified in the COPYING file
9
 * distributed with the Net-SNMP package.
10
 *
11
 * Portions of this file are copyrighted by:
12
 * Copyright (c) 2016 VMware, Inc. All rights reserved.
13
 * Use is subject to license terms specified in the COPYING file
14
 * distributed with the Net-SNMP package.
15
 */
16
#include <net-snmp/net-snmp-config.h>
17
#include <net-snmp/net-snmp-features.h>
18
19
#include <net-snmp/net-snmp-includes.h>
20
#include <net-snmp/agent/net-snmp-agent-includes.h>
21
22
#include <net-snmp/agent/instance.h>
23
24
#include <stdlib.h>
25
#ifdef HAVE_STRING_H
26
#include <string.h>
27
#else
28
#include <strings.h>
29
#endif
30
31
#include <net-snmp/net-snmp-includes.h>
32
#include <net-snmp/agent/serialize.h>
33
#include <net-snmp/agent/read_only.h>
34
35
netsnmp_feature_provide(instance);
36
netsnmp_feature_child_of(instance, mib_helpers);
37
38
typedef struct netsnmp_num_file_instance_s {
39
    int   refcnt;
40
    char *file_name;
41
    FILE *filep;
42
    u_char type;
43
    int   flags;
44
} netsnmp_num_file_instance;
45
46
#ifndef NETSNMP_FEATURE_REMOVE_REGISTER_NUM_FILE_INSTANCE
47
/** @defgroup instance instance
48
 *  Process individual MIB instances easily.
49
 *  @ingroup leaf
50
 *  @{
51
 */
52
53
static void *
54
netsnmp_num_file_instance_ref(void *p)
55
0
{
56
0
    netsnmp_num_file_instance *nfi = p;
57
58
0
    nfi->refcnt++;
59
0
    return nfi;
60
0
}
61
62
static void
63
netsnmp_num_file_instance_deref(void *p)
64
0
{
65
0
    netsnmp_num_file_instance *nfi = p;
66
67
0
    if (--nfi->refcnt == 0) {
68
0
  free(nfi->file_name);
69
0
  free(nfi);
70
0
    }
71
0
}
72
#endif /* NETSNMP_FEATURE_REMOVE_REGISTER_NUM_FILE_INSTANCE */
73
74
/**
75
 * Creates an instance helper handler, calls netsnmp_create_handler, which
76
 * then could be registered, using netsnmp_register_handler().
77
 *
78
 * @return Returns a pointer to a netsnmp_mib_handler struct which contains
79
 *  the handler's name and the access method
80
 */
81
netsnmp_mib_handler *
82
netsnmp_get_instance_handler(void)
83
0
{
84
0
    return netsnmp_create_handler("instance",
85
0
                                  netsnmp_instance_helper_handler);
86
0
}
87
88
/**
89
 * This function registers an instance helper handler, which is a way of 
90
 * registering an exact OID such that GENEXT requests are handled entirely
91
 * by the helper. First need to inject it into the calling chain of the 
92
 * handler defined by the netsnmp_handler_registration struct, reginfo.  
93
 * The new handler is injected at the top of the list and will be the new
94
 * handler to be called first.  This function also injects a serialize 
95
 * handler before actually calling netsnmp_register_handle, registering 
96
 * reginfo.
97
 *
98
 * @param reginfo a handler registration structure which could get created
99
 *                using netsnmp_create_handler_registration.  Used to register
100
 *                an instance helper handler.
101
 *
102
 * @return
103
 *      MIB_REGISTERED_OK is returned if the registration was a success.
104
 *  Failures are MIB_REGISTRATION_FAILED and MIB_DUPLICATE_REGISTRATION.
105
 */
106
int
107
netsnmp_register_instance(netsnmp_handler_registration *reginfo)
108
0
{
109
0
    netsnmp_mib_handler *handler = netsnmp_get_instance_handler();
110
0
    if (handler) {
111
0
        handler->flags |= MIB_HANDLER_INSTANCE;
112
0
        if (netsnmp_inject_handler(reginfo, handler) == SNMPERR_SUCCESS)
113
0
            return netsnmp_register_serialize(reginfo);
114
0
    }
115
116
0
    snmp_log(LOG_ERR, "failed to register instance\n");
117
0
    netsnmp_handler_free(handler);
118
0
    netsnmp_handler_registration_free(reginfo);
119
120
0
    return MIB_REGISTRATION_FAILED;
121
0
}
122
123
/**
124
 * This function injects a "read only" handler into the handler chain 
125
 * prior to serializing/registering the handler.
126
 *
127
 * The only purpose of this "read only" handler is to return an
128
 * appropriate error for any requests passed to it in a SET mode.
129
 * Inserting it into your handler chain will ensure you're never
130
 * asked to perform a SET request so you can ignore those error
131
 * conditions.
132
 *
133
 * @param reginfo a handler registration structure which could get created
134
 *                using netsnmp_create_handler_registration.  Used to register
135
 *                a read only instance helper handler.
136
 *
137
 * @return
138
 *      MIB_REGISTERED_OK is returned if the registration was a success.
139
 *  Failures are MIB_REGISTRATION_FAILED and MIB_DUPLICATE_REGISTRATION.
140
 */
141
int
142
netsnmp_register_read_only_instance(netsnmp_handler_registration *reginfo)
143
0
{
144
0
    netsnmp_mib_handler *h1, *h2;
145
0
    if (!reginfo)
146
0
        return MIB_REGISTRATION_FAILED;
147
148
0
    h1 = netsnmp_get_instance_handler();
149
0
    h2 = netsnmp_get_read_only_handler();
150
0
    if (h1 && h2 && netsnmp_inject_handler(reginfo, h1) == SNMPERR_SUCCESS) {
151
0
        h1 = NULL;
152
0
        if (netsnmp_inject_handler(reginfo, h2) == SNMPERR_SUCCESS)
153
0
            return netsnmp_register_serialize(reginfo);
154
0
    }
155
156
0
    snmp_log(LOG_ERR, "failed to register read only instance\n");
157
0
    netsnmp_handler_free(h1);
158
0
    netsnmp_handler_free(h2);
159
0
    netsnmp_handler_registration_free(reginfo);
160
161
0
   return MIB_REGISTRATION_FAILED;
162
0
}
163
164
#ifndef NETSNMP_FEATURE_REMOVE_REGISTER_NUM_FILE_INSTANCE
165
static
166
netsnmp_handler_registration *
167
get_reg(const char *name,
168
        const char *ourname,
169
        const oid * reg_oid, size_t reg_oid_len,
170
        netsnmp_num_file_instance *it,
171
        int modes,
172
        Netsnmp_Node_Handler * scalarh, Netsnmp_Node_Handler * subhandler,
173
        const char *contextName)
174
0
{
175
0
    netsnmp_handler_registration *myreg;
176
0
    netsnmp_mib_handler *myhandler;
177
178
0
    if (subhandler) {
179
0
        myreg =
180
0
            netsnmp_create_handler_registration(name, subhandler, reg_oid,
181
0
                                                reg_oid_len, modes);
182
0
        if (!myreg)
183
0
            return NULL;
184
0
        myhandler = netsnmp_create_handler(ourname, scalarh);
185
0
        if (!myhandler) {
186
0
            netsnmp_handler_registration_free(myreg);
187
0
            return NULL;
188
0
        }
189
0
        myhandler->myvoid = it;
190
0
  myhandler->data_clone = (void*(*)(void*))netsnmp_num_file_instance_ref;
191
0
  myhandler->data_free = (void(*)(void*))netsnmp_num_file_instance_deref;
192
0
        if (netsnmp_inject_handler(myreg, myhandler) != SNMPERR_SUCCESS) {
193
0
            netsnmp_handler_free(myhandler);
194
0
            netsnmp_handler_registration_free(myreg);
195
0
            return NULL;
196
0
        }
197
0
    } else {
198
0
        myreg = netsnmp_create_handler_registration(name, scalarh, reg_oid,
199
0
                                                    reg_oid_len, modes);
200
0
        if (!myreg)
201
0
            return NULL;
202
0
        myreg->handler->myvoid = it;
203
0
  myreg->handler->data_clone = netsnmp_num_file_instance_ref;
204
0
  myreg->handler->data_free = netsnmp_num_file_instance_deref;
205
0
    }
206
0
    if (contextName) {
207
0
        myreg->contextName = strdup(contextName);
208
0
        if (!myreg->contextName) {
209
0
            netsnmp_handler_registration_free(myreg);
210
0
            return NULL;
211
0
        }
212
0
    }
213
214
0
    return myreg;
215
0
}
216
#endif /* NETSNMP_FEATURE_REMOVE_REGISTER_NUM_FILE_INSTANCE */
217
218
/* Watched 'long' instances are writable on both 32-bit and 64-bit systems  */
219
netsnmp_feature_child_of(read_only_ulong_instance,instance);
220
#ifndef NETSNMP_FEATURE_REMOVE_READ_ONLY_ULONG_INSTANCE
221
int
222
netsnmp_register_read_only_ulong_instance(const char *name,
223
                                          const oid * reg_oid,
224
                                          size_t reg_oid_len, u_long * it,
225
                                          Netsnmp_Node_Handler *
226
                                          subhandler)
227
0
{
228
0
    return netsnmp_register_watched_instance2(
229
0
               netsnmp_create_handler_registration(
230
0
                   name, subhandler, reg_oid, reg_oid_len, HANDLER_CAN_RONLY),
231
0
               netsnmp_create_watcher_info(
232
0
                   (void *)it, sizeof(u_long),
233
0
                   ASN_UNSIGNED, WATCHER_FIXED_SIZE));
234
0
}
235
#endif /* NETSNMP_FEATURE_REMOVE_READ_ONLY_ULONG_INSTANCE */
236
237
netsnmp_feature_child_of(ulong_instance,instance);
238
#ifndef NETSNMP_FEATURE_REMOVE_ULONG_INSTANCE
239
int
240
netsnmp_register_ulong_instance(const char *name,
241
                                const oid * reg_oid, size_t reg_oid_len,
242
                                u_long * it,
243
                                Netsnmp_Node_Handler * subhandler)
244
0
{
245
0
    return netsnmp_register_watched_instance2(
246
0
               netsnmp_create_handler_registration(
247
0
                   name, subhandler, reg_oid, reg_oid_len, HANDLER_CAN_RWRITE),
248
0
               netsnmp_create_watcher_info(
249
0
                   (void *)it, sizeof(u_long),
250
0
                   ASN_UNSIGNED, WATCHER_FIXED_SIZE));
251
0
}
252
#endif /* NETSNMP_FEATURE_REMOVE_ULONG_INSTANCE */
253
254
netsnmp_feature_child_of(read_only_counter32_instance,instance);
255
#ifndef NETSNMP_FEATURE_REMOVE_READ_ONLY_COUNTER32_INSTANCE
256
int
257
netsnmp_register_read_only_counter32_instance(const char *name,
258
                                              const oid * reg_oid,
259
                                              size_t reg_oid_len,
260
                                              u_long * it,
261
                                              Netsnmp_Node_Handler *
262
                                              subhandler)
263
0
{
264
0
    return netsnmp_register_watched_instance2(
265
0
               netsnmp_create_handler_registration(
266
0
                   name, subhandler, reg_oid, reg_oid_len, HANDLER_CAN_RONLY),
267
0
               netsnmp_create_watcher_info(
268
0
                   (void *)it, sizeof(u_long),
269
0
                   ASN_COUNTER, WATCHER_FIXED_SIZE));
270
0
}
271
#endif /* NETSNMP_FEATURE_REMOVE_READ_ONLY_COUNTER32_INSTANCE */
272
273
netsnmp_feature_child_of(read_only_long_instance,instance);
274
#ifndef NETSNMP_FEATURE_REMOVE_READ_ONLY_LONG_INSTANCE
275
int
276
netsnmp_register_read_only_long_instance(const char *name,
277
                                         const oid * reg_oid,
278
                                         size_t reg_oid_len,
279
                                         long *it,
280
                                         Netsnmp_Node_Handler * subhandler)
281
0
{
282
0
    return netsnmp_register_watched_instance2(
283
0
               netsnmp_create_handler_registration(
284
0
                   name, subhandler, reg_oid, reg_oid_len, HANDLER_CAN_RONLY),
285
0
               netsnmp_create_watcher_info(
286
0
                   (void *)it, sizeof(long), ASN_INTEGER, WATCHER_FIXED_SIZE));
287
0
}
288
#endif /* NETSNMP_FEATURE_REMOVE_READ_ONLY_LONG_INSTANCE */
289
290
netsnmp_feature_child_of(long_instance,instance);
291
#ifndef NETSNMP_FEATURE_REMOVE_LONG_INSTANCE
292
int
293
netsnmp_register_long_instance(const char *name,
294
                               const oid * reg_oid, size_t reg_oid_len,
295
                               long *it, Netsnmp_Node_Handler * subhandler)
296
0
{
297
0
    return netsnmp_register_watched_instance2(
298
0
               netsnmp_create_handler_registration(
299
0
                   name, subhandler, reg_oid, reg_oid_len, HANDLER_CAN_RWRITE),
300
0
               netsnmp_create_watcher_info(
301
0
                   (void *)it, sizeof(long), ASN_INTEGER, WATCHER_FIXED_SIZE));
302
0
}
303
#endif /* NETSNMP_FEATURE_REMOVE_LONG_INSTANCE */
304
305
/* Watched 'int' instances are only writable on 32-bit systems  */
306
netsnmp_feature_child_of(read_only_uint_instance,instance);
307
#ifndef NETSNMP_FEATURE_REMOVE_READ_ONLY_UINT_INSTANCE
308
int
309
netsnmp_register_read_only_uint_instance(const char *name,
310
                                         const oid * reg_oid,
311
                                         size_t reg_oid_len,
312
                                         unsigned int *it,
313
                                         Netsnmp_Node_Handler * subhandler)
314
0
{
315
0
    return netsnmp_register_watched_instance2(
316
0
               netsnmp_create_handler_registration(
317
0
                   name, subhandler, reg_oid, reg_oid_len, HANDLER_CAN_RONLY),
318
0
               netsnmp_create_watcher_info(
319
0
                   (void *)it, sizeof(unsigned int),
320
0
                   ASN_UNSIGNED, WATCHER_FIXED_SIZE));
321
0
}
322
#endif /* NETSNMP_FEATURE_REMOVE_READ_ONLY_UINT_INSTANCE */
323
324
netsnmp_feature_child_of(uint_instance,instance);
325
#ifndef NETSNMP_FEATURE_REMOVE_UINT_INSTANCE
326
int
327
netsnmp_register_uint_instance(const char *name,
328
                               const oid * reg_oid, size_t reg_oid_len,
329
                               unsigned int *it, Netsnmp_Node_Handler * subhandler)
330
0
{
331
0
    return netsnmp_register_watched_instance2(
332
0
               netsnmp_create_handler_registration(
333
0
                   name, subhandler, reg_oid, reg_oid_len, HANDLER_CAN_RWRITE),
334
0
               netsnmp_create_watcher_info(
335
0
                   (void *)it, sizeof(unsigned int),
336
0
                   ASN_UNSIGNED, WATCHER_FIXED_SIZE));
337
0
}
338
#endif /* NETSNMP_FEATURE_REMOVE_UINT_INSTANCE */
339
340
netsnmp_feature_child_of(read_only_int_instance,instance);
341
#ifndef NETSNMP_FEATURE_REMOVE_READ_ONLY_INT_INSTANCE
342
int
343
netsnmp_register_read_only_int_instance(const char *name,
344
                                const oid * reg_oid, size_t reg_oid_len,
345
                                int *it, Netsnmp_Node_Handler * subhandler)
346
0
{
347
0
    return netsnmp_register_watched_instance2(
348
0
               netsnmp_create_handler_registration(
349
0
                   name, subhandler, reg_oid, reg_oid_len, HANDLER_CAN_RONLY),
350
0
               netsnmp_create_watcher_info(
351
0
                   (void *)it, sizeof(int), ASN_INTEGER, WATCHER_FIXED_SIZE));
352
0
}
353
#endif /* NETSNMP_FEATURE_REMOVE_READ_ONLY_INT_INSTANCE */
354
355
  /*
356
   * Compatibility with earlier (inconsistently named) routine
357
   */
358
netsnmp_feature_child_of(register_read_only_int_instance,netsnmp_unused);
359
#ifndef NETSNMP_FEATURE_REMOVE_REGISTER_READ_ONLY_INT_INSTANCE
360
int
361
register_read_only_int_instance(const char *name,
362
                                const oid * reg_oid, size_t reg_oid_len,
363
                                int *it, Netsnmp_Node_Handler * subhandler)
364
0
{
365
0
  return netsnmp_register_read_only_int_instance(name,
366
0
                                reg_oid, reg_oid_len,
367
0
                                it, subhandler);
368
0
}
369
#endif /* NETSNMP_FEATURE_REMOVE_REGISTER_READ_ONLY_INT_INSTANCE */
370
371
/*
372
 * Context registrations
373
 */
374
375
netsnmp_feature_child_of(register_read_only_ulong_instance_context,instance);
376
#ifndef NETSNMP_FEATURE_REMOVE_REGISTER_READ_ONLY_ULONG_INSTANCE_CONTEXT
377
int
378
netsnmp_register_read_only_ulong_instance_context(const char *name,
379
                                                  const oid * reg_oid,
380
                                                  size_t reg_oid_len,
381
                                                  u_long * it,
382
                                                  Netsnmp_Node_Handler *
383
                                                  subhandler,
384
                                                  const char *contextName)
385
0
{
386
0
    netsnmp_handler_registration *myreg =
387
0
      netsnmp_create_handler_registration(
388
0
          name, subhandler, reg_oid, reg_oid_len, HANDLER_CAN_RONLY);
389
0
    if (myreg && contextName)
390
0
      myreg->contextName = strdup(contextName);
391
0
    return netsnmp_register_watched_instance2(
392
0
        myreg, netsnmp_create_watcher_info(
393
0
            (void *)it, sizeof(u_long), ASN_UNSIGNED, WATCHER_FIXED_SIZE));
394
0
}
395
#endif /* NETSNMP_FEATURE_REMOVE_REGISTER_READ_ONLY_ULONG_INSTANCE_CONTEXT */
396
397
netsnmp_feature_child_of(register_ulong_instance_context,instance);
398
#ifndef NETSNMP_FEATURE_REMOVE_REGISTER_ULONG_INSTANCE_CONTEXT
399
int
400
netsnmp_register_ulong_instance_context(const char *name,
401
                                        const oid * reg_oid, size_t reg_oid_len,
402
                                        u_long * it,
403
                                        Netsnmp_Node_Handler * subhandler,
404
                                        const char *contextName)
405
0
{
406
0
    netsnmp_handler_registration *myreg =
407
0
      netsnmp_create_handler_registration(
408
0
          name, subhandler, reg_oid, reg_oid_len, HANDLER_CAN_RWRITE);
409
0
    if (myreg && contextName)
410
0
      myreg->contextName = strdup(contextName);
411
0
    return netsnmp_register_watched_instance2(
412
0
        myreg, netsnmp_create_watcher_info(
413
0
            (void *)it, sizeof(u_long), ASN_UNSIGNED, WATCHER_FIXED_SIZE));
414
0
}
415
#endif /* NETSNMP_FEATURE_REMOVE_REGISTER_ULONG_INSTANCE_CONTEXT */
416
417
netsnmp_feature_child_of(register_read_only_counter32_instance_context,instance);
418
#ifndef NETSNMP_FEATURE_REMOVE_REGISTER_READ_ONLY_COUNTER32_INSTANCE_CONTEXT
419
int
420
netsnmp_register_read_only_counter32_instance_context(const char *name,
421
                                                      const oid * reg_oid,
422
                                                      size_t reg_oid_len,
423
                                                      u_long * it,
424
                                                      Netsnmp_Node_Handler *
425
                                                      subhandler,
426
                                                      const char *contextName)
427
0
{
428
0
    netsnmp_handler_registration *myreg =
429
0
      netsnmp_create_handler_registration(
430
0
          name, subhandler, reg_oid, reg_oid_len, HANDLER_CAN_RONLY);
431
0
    if (myreg && contextName)
432
0
      myreg->contextName = strdup(contextName);
433
0
    return netsnmp_register_watched_instance2(
434
0
        myreg, netsnmp_create_watcher_info(
435
0
            (void *)it, sizeof(u_long), ASN_COUNTER, WATCHER_FIXED_SIZE));
436
0
}
437
#endif /* NETSNMP_FEATURE_REMOVE_REGISTER_READ_ONLY_COUNTER32_INSTANCE_CONTEXT */
438
439
netsnmp_feature_child_of(register_read_only_long_instance_context,instance);
440
#ifndef NETSNMP_FEATURE_REMOVE_REGISTER_READ_ONLY_LONG_INSTANCE_CONTEXT
441
int
442
netsnmp_register_read_only_long_instance_context(const char *name,
443
                                                 const oid * reg_oid,
444
                                                 size_t reg_oid_len,
445
                                                 long *it,
446
                                                 Netsnmp_Node_Handler
447
                                                 *subhandler,
448
                                                 const char *contextName)
449
0
{
450
0
    netsnmp_handler_registration *myreg =
451
0
      netsnmp_create_handler_registration(
452
0
          name, subhandler, reg_oid, reg_oid_len, HANDLER_CAN_RONLY);
453
0
    if (myreg && contextName)
454
0
      myreg->contextName = strdup(contextName);
455
0
    return netsnmp_register_watched_instance2(
456
0
        myreg, netsnmp_create_watcher_info(
457
0
            (void *)it, sizeof(long), ASN_INTEGER, WATCHER_FIXED_SIZE));
458
0
}
459
#endif /* NETSNMP_FEATURE_REMOVE_REGISTER_READ_ONLY_LONG_INSTANCE_CONTEXT */
460
461
netsnmp_feature_child_of(register_long_instance_context,instance);
462
#ifndef NETSNMP_FEATURE_REMOVE_REGISTER_LONG_INSTANCE_CONTEXT
463
int
464
netsnmp_register_long_instance_context(const char *name,
465
                                       const oid * reg_oid, size_t reg_oid_len,
466
                                       long *it,
467
                                       Netsnmp_Node_Handler * subhandler,
468
                                       const char *contextName)
469
0
{
470
0
    netsnmp_handler_registration *myreg =
471
0
      netsnmp_create_handler_registration(
472
0
          name, subhandler, reg_oid, reg_oid_len, HANDLER_CAN_RWRITE);
473
0
    if (myreg && contextName)
474
0
      myreg->contextName = strdup(contextName);
475
0
    return netsnmp_register_watched_instance2(
476
0
        myreg, netsnmp_create_watcher_info(
477
0
            (void *)it, sizeof(long), ASN_INTEGER, WATCHER_FIXED_SIZE));
478
0
}
479
#endif /* NETSNMP_FEATURE_REMOVE_REGISTER_LONG_INSTANCE_CONTEXT */
480
481
netsnmp_feature_child_of(register_int_instance_context,instance);
482
#ifndef NETSNMP_FEATURE_REMOVE_REGISTER_INT_INSTANCE_CONTEXT
483
int
484
netsnmp_register_int_instance_context(const char *name,
485
                                      const oid * reg_oid,
486
                                      size_t reg_oid_len,
487
                                      int *it,
488
                                      Netsnmp_Node_Handler * subhandler,
489
                                      const char *contextName)
490
0
{
491
0
    netsnmp_handler_registration *myreg =
492
0
      netsnmp_create_handler_registration(
493
0
          name, subhandler, reg_oid, reg_oid_len, HANDLER_CAN_RWRITE);
494
0
    if (myreg && contextName)
495
0
      myreg->contextName = strdup(contextName);
496
0
    return netsnmp_register_watched_instance2(
497
0
        myreg, netsnmp_create_watcher_info(
498
0
            (void *)it, sizeof(int), ASN_INTEGER, WATCHER_FIXED_SIZE));
499
0
}
500
#endif /* NETSNMP_FEATURE_REMOVE_REGISTER_INT_INSTANCE_CONTEXT */
501
502
netsnmp_feature_child_of(register_read_only_int_instance_context,instance);
503
#ifndef NETSNMP_FEATURE_REMOVE_REGISTER_READ_ONLY_INT_INSTANCE_CONTEXT
504
int
505
netsnmp_register_read_only_int_instance_context(const char *name,
506
                                                const oid * reg_oid,
507
                                                size_t reg_oid_len,
508
                                                int *it,
509
                                                Netsnmp_Node_Handler * subhandler,
510
                                                const char *contextName)
511
0
{
512
0
    netsnmp_handler_registration *myreg =
513
0
      netsnmp_create_handler_registration(
514
0
          name, subhandler, reg_oid, reg_oid_len, HANDLER_CAN_RONLY);
515
0
    if (myreg && contextName)
516
0
      myreg->contextName = strdup(contextName);
517
0
    return netsnmp_register_watched_instance2(
518
0
        myreg, netsnmp_create_watcher_info(
519
0
            (void *)it, sizeof(int), ASN_INTEGER, WATCHER_FIXED_SIZE));
520
0
}
521
#endif /* NETSNMP_FEATURE_REMOVE_REGISTER_READ_ONLY_INT_INSTANCE_CONTEXT */
522
523
/*
524
 * Compatibility with earlier (inconsistently named) routine
525
 */
526
netsnmp_feature_child_of(read_only_int_instance_context,instance);
527
#ifndef NETSNMP_FEATURE_REMOVE_READ_ONLY_INT_INSTANCE_CONTEXT
528
int
529
register_read_only_int_instance_context(const char *name,
530
                                        const oid * reg_oid, size_t reg_oid_len,
531
                                        int *it,
532
                                        Netsnmp_Node_Handler * subhandler,
533
                                        const char *contextName)
534
0
{
535
0
    return netsnmp_register_read_only_int_instance_context(name,
536
0
                                                           reg_oid, reg_oid_len,
537
0
                                                           it, subhandler,
538
0
                                                           contextName);
539
0
}
540
#endif /* NETSNMP_FEATURE_REMOVE_READ_ONLY_INT_INSTANCE_CONTEXT */
541
542
netsnmp_feature_child_of(register_num_file_instance,instance);
543
#ifndef NETSNMP_FEATURE_REMOVE_REGISTER_NUM_FILE_INSTANCE
544
int
545
netsnmp_register_num_file_instance(const char *name,
546
                                   const oid * reg_oid, size_t reg_oid_len,
547
                                   const char *file_name, int asn_type, int mode,
548
                                   Netsnmp_Node_Handler * subhandler,
549
                                   const char *contextName)
550
0
{
551
0
    netsnmp_handler_registration *myreg;
552
0
    netsnmp_num_file_instance *nfi;
553
554
0
    if ((NULL == name) || (NULL == reg_oid) || (NULL == file_name)) {
555
0
        snmp_log(LOG_ERR, "bad parameter to netsnmp_register_num_file_instance\n");
556
0
        return MIB_REGISTRATION_FAILED;
557
0
    }
558
559
0
    nfi = SNMP_MALLOC_TYPEDEF(netsnmp_num_file_instance);
560
0
    if ((NULL == nfi) ||
561
0
        (NULL == (nfi->file_name = strdup(file_name)))) {
562
0
        snmp_log(LOG_ERR, "could not not allocate memory\n");
563
0
        if (NULL != nfi)
564
0
            free(nfi); /* SNMP_FREE overkill on local var */
565
0
        return MIB_REGISTRATION_FAILED;
566
0
    }
567
568
0
    nfi->refcnt = 1;
569
0
    myreg = get_reg(name, "file_num_handler", reg_oid, reg_oid_len, nfi,
570
0
                    mode, netsnmp_instance_num_file_handler,
571
0
                    subhandler, contextName);
572
0
    if (NULL == myreg) {
573
0
        netsnmp_num_file_instance_deref(nfi);
574
0
        return MIB_REGISTRATION_FAILED;
575
0
    }
576
577
0
    nfi->type = asn_type;
578
579
0
    if (HANDLER_CAN_RONLY == mode)
580
0
        return netsnmp_register_read_only_instance(myreg);
581
582
0
    return netsnmp_register_instance(myreg);
583
0
}
584
#endif /* NETSNMP_FEATURE_REMOVE_REGISTER_NUM_FILE_INSTANCE */
585
586
netsnmp_feature_child_of(register_int_instance,instance);
587
#ifndef NETSNMP_FEATURE_REMOVE_REGISTER_INT_INSTANCE
588
/**
589
 * This function registers an int helper handler to a specified OID.
590
 *
591
 * @param name         the name used for registration purposes.
592
 *
593
 * @param reg_oid      the OID where you want to register your integer at
594
 *
595
 * @param reg_oid_len  the length of the OID
596
 *
597
 * @param it           the integer value to be registered during initialization
598
 *
599
 * @param subhandler   a handler to do whatever you want to do, otherwise use
600
 *                     NULL to use the default int handler.
601
 *
602
 * @return
603
 *      MIB_REGISTERED_OK is returned if the registration was a success.
604
 *  Failures are MIB_REGISTRATION_FAILED and MIB_DUPLICATE_REGISTRATION.
605
 */
606
int
607
netsnmp_register_int_instance(const char *name,
608
                              const oid * reg_oid, size_t reg_oid_len,
609
                              int *it, Netsnmp_Node_Handler * subhandler)
610
0
{
611
0
    return netsnmp_register_watched_instance2(
612
0
               netsnmp_create_handler_registration(
613
0
                   name, subhandler, reg_oid, reg_oid_len, HANDLER_CAN_RWRITE),
614
0
               netsnmp_create_watcher_info(
615
0
                   (void *)it, sizeof(int), ASN_INTEGER, WATCHER_FIXED_SIZE));
616
0
}
617
#endif /* NETSNMP_FEATURE_REMOVE_REGISTER_INT_INSTANCE */
618
619
#ifdef HAVE_DMALLOC_H
620
static void free_wrapper(void * p)
621
{
622
    free(p);
623
}
624
#else
625
0
#define free_wrapper free
626
#endif
627
628
int
629
netsnmp_instance_num_file_handler(netsnmp_mib_handler *handler,
630
                                  netsnmp_handler_registration *reginfo,
631
                                  netsnmp_agent_request_info *reqinfo,
632
                                  netsnmp_request_info *requests)
633
0
{
634
0
    netsnmp_num_file_instance *nfi;
635
0
    u_long it;
636
0
#ifndef NETSNMP_NO_WRITE_SUPPORT
637
0
    u_long *it_save;
638
0
#endif /* NETSNMP_NO_WRITE_SUPPORT */
639
0
    int rc;
640
641
0
    netsnmp_assert(NULL != handler);
642
0
    nfi = (netsnmp_num_file_instance *)handler->myvoid;
643
0
    netsnmp_assert(NULL != nfi);
644
0
    netsnmp_assert(NULL != nfi->file_name);
645
646
0
    DEBUGMSGTL(("netsnmp_instance_int_handler", "Got request:  %d\n",
647
0
                reqinfo->mode));
648
649
0
    switch (reqinfo->mode) {
650
        /*
651
         * data requests 
652
         */
653
0
    case MODE_GET:
654
  /*
655
   * Use a long here, otherwise on 64 bit use of an int would fail
656
   */
657
0
        netsnmp_assert(NULL == nfi->filep);
658
0
        nfi->filep = fopen(nfi->file_name, "r");
659
0
        if (NULL == nfi->filep) {
660
0
            netsnmp_set_request_error(reqinfo, requests,
661
0
                                      SNMP_NOSUCHINSTANCE);
662
0
            return SNMP_ERR_NOERROR;
663
0
        }
664
0
        rc = fscanf(nfi->filep, (nfi->type == ASN_INTEGER) ? "%ld" : "%lu",
665
0
                    &it);
666
0
        fclose(nfi->filep);
667
0
        nfi->filep = NULL;
668
0
        if (rc != 1) {
669
0
            netsnmp_set_request_error(reqinfo, requests,
670
0
                                      SNMP_NOSUCHINSTANCE);
671
0
            return SNMP_ERR_NOERROR;
672
0
        }
673
0
        snmp_set_var_typed_value(requests->requestvb, nfi->type,
674
0
                                 (u_char *) &it, sizeof(it));
675
0
        break;
676
677
        /*
678
         * SET requests.  Should only get here if registered RWRITE 
679
         */
680
0
#ifndef NETSNMP_NO_WRITE_SUPPORT
681
0
    case MODE_SET_RESERVE1:
682
0
        netsnmp_assert(NULL == nfi->filep);
683
0
        if (requests->requestvb->type != nfi->type)
684
0
            netsnmp_set_request_error(reqinfo, requests,
685
0
                                      SNMP_ERR_WRONGTYPE);
686
0
        break;
687
688
0
    case MODE_SET_RESERVE2:
689
0
        netsnmp_assert(NULL == nfi->filep);
690
0
        nfi->filep = fopen(nfi->file_name, "w+");
691
0
        if (NULL == nfi->filep) {
692
0
            netsnmp_set_request_error(reqinfo, requests,
693
0
                                      SNMP_ERR_NOTWRITABLE);
694
0
            return SNMP_ERR_NOERROR;
695
0
        }
696
        /*
697
         * store old info for undo later 
698
         */
699
0
        if (fscanf(nfi->filep, (nfi->type == ASN_INTEGER) ? "%ld" : "%lu",
700
0
                   &it) != 1) {
701
0
            netsnmp_set_request_error(reqinfo, requests,
702
0
                                      SNMP_ERR_RESOURCEUNAVAILABLE);
703
0
            return SNMP_ERR_NOERROR;
704
0
        }
705
706
0
        it_save = netsnmp_memdup(&it, sizeof(u_long));
707
0
        if (it_save == NULL) {
708
0
            netsnmp_set_request_error(reqinfo, requests,
709
0
                                      SNMP_ERR_RESOURCEUNAVAILABLE);
710
0
            return SNMP_ERR_NOERROR;
711
0
        }
712
0
        netsnmp_request_add_list_data(requests,
713
0
                                      netsnmp_create_data_list
714
0
                                      (INSTANCE_HANDLER_NAME, it_save,
715
0
                                       &free_wrapper));
716
0
        break;
717
718
0
    case MODE_SET_ACTION:
719
        /*
720
         * update current 
721
         */
722
0
        DEBUGMSGTL(("helper:instance", "updated %s -> %ld\n", nfi->file_name,
723
0
                    *(requests->requestvb->val.integer)));
724
0
        it = *(requests->requestvb->val.integer);
725
0
        rewind(nfi->filep); /* rewind to make sure we are at the beginning */
726
0
        rc = fprintf(nfi->filep, (nfi->type == ASN_INTEGER) ? "%ld" : "%lu",
727
0
                     it);
728
0
        if (rc < 0) {
729
0
            netsnmp_set_request_error(reqinfo, requests,
730
0
                                      SNMP_ERR_GENERR);
731
0
            return SNMP_ERR_NOERROR;
732
0
        }
733
0
        break;
734
735
0
    case MODE_SET_UNDO:
736
0
        it =
737
0
            *((u_int *) netsnmp_request_get_list_data(requests,
738
0
                                                      INSTANCE_HANDLER_NAME));
739
0
        rc = fprintf(nfi->filep, (nfi->type == ASN_INTEGER) ? "%ld" : "%lu",
740
0
                     it);
741
0
        if (rc < 0)
742
0
            netsnmp_set_request_error(reqinfo, requests,
743
0
                                      SNMP_ERR_UNDOFAILED);
744
0
        NETSNMP_FALLTHROUGH;
745
0
    case MODE_SET_COMMIT:
746
0
    case MODE_SET_FREE:
747
0
        if (NULL != nfi->filep) {
748
0
            fclose(nfi->filep);
749
0
            nfi->filep = NULL;
750
0
        }
751
0
        break;
752
0
#endif /* NETSNMP_NO_WRITE_SUPPORT */
753
0
    default:
754
0
        snmp_log(LOG_ERR,
755
0
                 "netsnmp_instance_num_file_handler: illegal mode\n");
756
0
        netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_GENERR);
757
0
        return SNMP_ERR_NOERROR;
758
0
    }
759
760
0
    if (handler->next && handler->next->access_method)
761
0
        return netsnmp_call_next_handler(handler, reginfo, reqinfo,
762
0
                                         requests);
763
0
    return SNMP_ERR_NOERROR;
764
0
}
765
766
int
767
netsnmp_instance_helper_handler(netsnmp_mib_handler *handler,
768
                                netsnmp_handler_registration *reginfo,
769
                                netsnmp_agent_request_info *reqinfo,
770
                                netsnmp_request_info *requests)
771
0
{
772
773
0
    netsnmp_variable_list *var = requests->requestvb;
774
775
0
    int             ret, cmp;
776
777
0
    DEBUGMSGTL(("helper:instance", "Got request:\n"));
778
0
    cmp = snmp_oid_compare(requests->requestvb->name,
779
0
                           requests->requestvb->name_length,
780
0
                           reginfo->rootoid, reginfo->rootoid_len);
781
782
0
    DEBUGMSGTL(("helper:instance", "  oid:"));
783
0
    DEBUGMSGOID(("helper:instance", var->name, var->name_length));
784
0
    DEBUGMSG(("helper:instance", "\n"));
785
786
0
    switch (reqinfo->mode) {
787
0
    case MODE_GET:
788
0
        if (cmp != 0) {
789
0
            netsnmp_set_request_error(reqinfo, requests,
790
0
                                      SNMP_NOSUCHINSTANCE);
791
0
            return SNMP_ERR_NOERROR;
792
0
        } else {
793
0
            return netsnmp_call_next_handler(handler, reginfo, reqinfo,
794
0
                                             requests);
795
0
        }
796
0
        break;
797
798
0
#ifndef NETSNMP_NO_WRITE_SUPPORT
799
0
    case MODE_SET_RESERVE1:
800
0
    case MODE_SET_RESERVE2:
801
0
    case MODE_SET_ACTION:
802
0
    case MODE_SET_COMMIT:
803
0
    case MODE_SET_UNDO:
804
0
    case MODE_SET_FREE:
805
0
        if (cmp != 0) {
806
0
            netsnmp_set_request_error(reqinfo, requests,
807
0
                                      SNMP_ERR_NOCREATION);
808
0
            return SNMP_ERR_NOERROR;
809
0
        } else {
810
0
            return netsnmp_call_next_handler(handler, reginfo, reqinfo,
811
0
                                             requests);
812
0
        }
813
0
        break;
814
0
#endif /* NETSNMP_NO_WRITE_SUPPORT */
815
816
0
    case MODE_GETNEXT:
817
0
        if (cmp < 0 || (cmp == 0 && requests->inclusive)) {
818
0
            reqinfo->mode = MODE_GET;
819
0
            snmp_set_var_objid(requests->requestvb, reginfo->rootoid,
820
0
                               reginfo->rootoid_len);
821
0
            ret =
822
0
                netsnmp_call_next_handler(handler, reginfo, reqinfo,
823
0
                                          requests);
824
0
            reqinfo->mode = MODE_GETNEXT;
825
            /*
826
             * if the instance doesn't have data, set type to ASN_NULL
827
             * to move to the next sub-tree. Ignore delegated requests; they
828
             * might have data later on.
829
             */
830
0
            if (!requests->delegated &&
831
0
                (requests->requestvb->type == SNMP_NOSUCHINSTANCE ||
832
0
                 requests->requestvb->type == SNMP_NOSUCHOBJECT)) {
833
0
                requests->requestvb->type = ASN_NULL;
834
0
            }
835
0
            return ret;
836
0
        } else {
837
0
            return SNMP_ERR_NOERROR;
838
0
        }
839
0
        break;
840
0
    default:
841
0
        snmp_log(LOG_ERR,
842
0
                 "netsnmp_instance_helper_handler: illegal mode\n");
843
0
        netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_GENERR);
844
0
        return SNMP_ERR_NOERROR;
845
0
    }
846
    /*
847
     * got here only if illegal mode found 
848
     */
849
0
    return SNMP_ERR_GENERR;
850
0
}
851
852
/** @} 
853
 */