Coverage Report

Created: 2025-12-14 06:46

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/net-snmp/agent/helpers/watcher.c
Line
Count
Source
1
/*
2
 * Portions of this file are subject to the following copyright(s).  See
3
 * the Net-SNMP's COPYING file for more details and other copyrights
4
 * that may apply:
5
 *
6
 * Portions of this file are copyrighted by:
7
 * Copyright (c) 2016 VMware, 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
12
#include <net-snmp/net-snmp-config.h>
13
#include <net-snmp/net-snmp-features.h>
14
15
#include <net-snmp/net-snmp-includes.h>
16
#include <net-snmp/agent/net-snmp-agent-includes.h>
17
18
#include <net-snmp/agent/watcher.h>
19
20
#include <net-snmp/agent/instance.h>
21
#include <net-snmp/agent/scalar.h>
22
23
#include <string.h>
24
25
#ifdef HAVE_DMALLOC_H
26
static void free_wrapper(void * p)
27
{
28
    free(p);
29
}
30
#else
31
0
#define free_wrapper free
32
#endif
33
34
netsnmp_feature_provide(watcher_all);
35
netsnmp_feature_child_of(watcher_all, mib_helpers);
36
netsnmp_feature_child_of(watcher_create_info6, watcher_all);
37
netsnmp_feature_child_of(watcher_register_timestamp, watcher_all);
38
netsnmp_feature_child_of(watcher_ulong_scalar, watcher_all);
39
netsnmp_feature_child_of(watcher_read_only_ulong_scalar, watcher_all);
40
netsnmp_feature_child_of(watcher_read_only_int_scalar, watcher_all);
41
netsnmp_feature_child_of(watcher_long_scalar, watcher_all);
42
netsnmp_feature_child_of(watcher_read_only_long_scalar, watcher_all);
43
netsnmp_feature_child_of(watcher_int_scalar, watcher_all);
44
netsnmp_feature_child_of(read_only_counter32_scalar, watcher_all);
45
netsnmp_feature_child_of(watcher_spinlock, watcher_all);
46
47
/** @defgroup watcher watcher
48
 *  Watch a specified variable and process it as an instance or scalar object
49
 *  @ingroup leaf
50
 *  @{
51
 */
52
netsnmp_mib_handler *
53
netsnmp_get_watcher_handler(void)
54
0
{
55
0
    netsnmp_mib_handler *ret = NULL;
56
    
57
0
    ret = netsnmp_create_handler("watcher",
58
0
                                 netsnmp_watcher_helper_handler);
59
0
    if (ret) {
60
0
        ret->flags |= MIB_HANDLER_AUTO_NEXT;
61
0
    }
62
0
    return ret;
63
0
}
64
65
netsnmp_watcher_info *
66
netsnmp_init_watcher_info6(netsnmp_watcher_info *winfo,
67
                           void *data, size_t size, u_char type,
68
                           int flags, size_t max_size, size_t* size_p)
69
0
{
70
0
    winfo->data = data;
71
0
    winfo->data_size = size;
72
0
    winfo->max_size = max_size;
73
0
    winfo->type = type;
74
0
    winfo->flags = flags;
75
0
    winfo->data_size_p = size_p;
76
0
    return winfo;
77
0
}
78
79
#ifndef NETSNMP_FEATURE_REMOVE_WATCHER_CREATE_INFO6
80
netsnmp_watcher_info *
81
netsnmp_create_watcher_info6(void *data, size_t size, u_char type,
82
                             int flags, size_t max_size, size_t* size_p)
83
0
{
84
0
    netsnmp_watcher_info *winfo = SNMP_MALLOC_TYPEDEF(netsnmp_watcher_info);
85
0
    if (winfo)
86
0
        netsnmp_init_watcher_info6(winfo, data, size, type, flags, max_size,
87
0
                                   size_p);
88
0
    return winfo;
89
0
}
90
#endif /* NETSNMP_FEATURE_REMOVE_WATCHER_CREATE_INFO6 */
91
92
netsnmp_watcher_info *
93
netsnmp_init_watcher_info(netsnmp_watcher_info *winfo,
94
                          void *data, size_t size, u_char type, int flags)
95
0
{
96
0
  return netsnmp_init_watcher_info6(winfo, data, size,
97
0
            type, (flags ? flags : WATCHER_FIXED_SIZE),
98
0
            size,  /* Probably wrong for non-fixed
99
              * size data */
100
0
            NULL);
101
0
}
102
103
netsnmp_watcher_info *
104
netsnmp_create_watcher_info(void *data, size_t size, u_char type, int flags)
105
0
{
106
0
    netsnmp_watcher_info *winfo = SNMP_MALLOC_TYPEDEF(netsnmp_watcher_info);
107
0
    if (winfo)
108
0
        netsnmp_init_watcher_info(winfo, data, size, type, flags);
109
0
    return winfo;
110
0
}
111
112
/**
113
 * Register a watched scalar. The caller remains the owner of watchinfo.
114
 *
115
 * @see netsnmp_register_watched_instance2()
116
 */
117
int
118
netsnmp_register_watched_instance(netsnmp_handler_registration *reginfo,
119
                                  netsnmp_watcher_info         *watchinfo)
120
0
{
121
0
    netsnmp_mib_handler *whandler = NULL;
122
123
0
    if (reginfo && watchinfo) {
124
0
        whandler = netsnmp_get_watcher_handler();
125
0
        if (whandler) {
126
0
            whandler->myvoid = (void *)watchinfo;
127
0
            if (netsnmp_inject_handler(reginfo, whandler) == SNMPERR_SUCCESS)
128
0
                return netsnmp_register_instance(reginfo);
129
0
        }
130
0
    }
131
132
0
    snmp_log(LOG_ERR, "could not create watched instance handler\n");
133
0
    netsnmp_handler_free(whandler);
134
0
    netsnmp_handler_registration_free(reginfo);
135
136
0
    return MIB_REGISTRATION_FAILED;
137
0
}
138
139
/**
140
 * Register a watched scalar. Ownership of watchinfo is transferred to the handler.
141
 *
142
 * @see netsnmp_register_watched_instance()
143
 */
144
int
145
netsnmp_register_watched_instance2(netsnmp_handler_registration *reginfo,
146
           netsnmp_watcher_info         *watchinfo)
147
0
{
148
0
    netsnmp_mib_handler *whandler = NULL;
149
150
0
    if (reginfo && watchinfo) {
151
0
        whandler = netsnmp_get_watcher_handler();
152
0
        if (whandler) {
153
0
            whandler->myvoid = (void *)watchinfo;
154
0
            netsnmp_owns_watcher_info(whandler);
155
0
            if (netsnmp_inject_handler(reginfo, whandler) == SNMPERR_SUCCESS)
156
0
                return netsnmp_register_instance(reginfo);
157
0
        }
158
0
    }
159
160
0
    snmp_log(LOG_ERR, "could not create watched instance2 handler\n");
161
0
    netsnmp_handler_free(whandler);
162
0
    netsnmp_handler_registration_free(reginfo);
163
164
0
    return MIB_REGISTRATION_FAILED;
165
0
}
166
167
/**
168
 * Register a watched scalar. The caller remains the owner of watchinfo.
169
 *
170
 * @see netsnmp_register_watched_scalar2()
171
 */
172
int
173
netsnmp_register_watched_scalar(netsnmp_handler_registration *reginfo,
174
                                  netsnmp_watcher_info         *watchinfo)
175
0
{
176
0
    netsnmp_mib_handler *whandler = NULL;
177
178
0
    if (reginfo && watchinfo) {
179
0
        whandler = netsnmp_get_watcher_handler();
180
0
        if (whandler) {
181
0
            whandler->myvoid = (void *)watchinfo;
182
0
            if (netsnmp_inject_handler(reginfo, whandler) == SNMPERR_SUCCESS)
183
0
                return netsnmp_register_scalar(reginfo);
184
0
        }
185
0
    }
186
187
0
    snmp_log(LOG_ERR, "could not create watched scalar handler\n");
188
0
    netsnmp_handler_free(whandler);
189
0
    netsnmp_handler_registration_free(reginfo);
190
191
0
    return MIB_REGISTRATION_FAILED;
192
0
}
193
194
/**
195
 * Register a watched scalar. Ownership of watchinfo is transferred to the handler.
196
 *
197
 * @see netsnmp_register_watched_scalar()
198
 */
199
int
200
netsnmp_register_watched_scalar2(netsnmp_handler_registration *reginfo,
201
                                  netsnmp_watcher_info         *watchinfo)
202
0
{
203
0
    netsnmp_mib_handler *whandler = NULL;
204
205
0
    if (reginfo && watchinfo) {
206
0
        whandler = netsnmp_get_watcher_handler();
207
0
        if (whandler) {
208
0
            whandler->myvoid = (void *)watchinfo;
209
0
            netsnmp_owns_watcher_info(whandler);
210
0
            if (netsnmp_inject_handler(reginfo, whandler) == SNMPERR_SUCCESS)
211
0
                return netsnmp_register_scalar(reginfo);
212
0
        }
213
0
    }
214
215
0
    snmp_log(LOG_ERR, "could not create watched scalar2 handler\n");
216
0
    netsnmp_handler_free(whandler);
217
0
    netsnmp_handler_registration_free(reginfo);
218
219
0
    return MIB_REGISTRATION_FAILED;
220
0
}
221
222
void
223
netsnmp_owns_watcher_info(netsnmp_mib_handler *handler)
224
0
{
225
0
    netsnmp_assert(handler);
226
0
    netsnmp_assert(handler->myvoid);
227
0
    handler->data_clone = netsnmp_clone_watcher_info;
228
0
    handler->data_free = free;
229
0
}
230
231
/** @cond */
232
233
NETSNMP_STATIC_INLINE size_t
234
get_data_size(const netsnmp_watcher_info* winfo)
235
0
{
236
0
    if (winfo->flags & WATCHER_SIZE_STRLEN)
237
0
        return strlen((const char*)winfo->data);
238
0
    else {
239
0
        size_t res;
240
0
        if (winfo->flags & WATCHER_SIZE_IS_PTR)
241
0
            res = *winfo->data_size_p;
242
0
        else
243
0
            res = winfo->data_size;
244
0
        if (winfo->flags & WATCHER_SIZE_UNIT_OIDS)
245
0
          res *= sizeof(oid);
246
0
        return res;
247
0
    }
248
0
}
249
250
NETSNMP_STATIC_INLINE void
251
set_data(netsnmp_watcher_info* winfo, void* data, size_t size)
252
0
{
253
0
    memcpy(winfo->data, data, size);
254
0
    if (winfo->flags & WATCHER_SIZE_STRLEN)
255
0
        ((char*)winfo->data)[size] = '\0';
256
0
    else {
257
0
        if (winfo->flags & WATCHER_SIZE_UNIT_OIDS)
258
0
          size /= sizeof(oid);
259
0
        if (winfo->flags & WATCHER_SIZE_IS_PTR)
260
0
            *winfo->data_size_p = size;
261
0
        else
262
0
            winfo->data_size = size;
263
0
    }
264
0
}
265
266
typedef struct {
267
    size_t size;
268
    char data[1];
269
} netsnmp_watcher_cache;
270
271
NETSNMP_STATIC_INLINE netsnmp_watcher_cache*
272
netsnmp_watcher_cache_create(const void* data, size_t size)
273
0
{
274
0
    netsnmp_watcher_cache *res = (netsnmp_watcher_cache*)
275
0
        malloc(sizeof(netsnmp_watcher_cache) + size - 1);
276
0
    if (res) {
277
0
        res->size = size;
278
0
        memcpy(res->data, data, size);
279
0
    }
280
0
    return res;
281
0
}
282
283
/** @endcond */
284
285
int
286
netsnmp_watcher_helper_handler(netsnmp_mib_handler *handler,
287
                               netsnmp_handler_registration *reginfo,
288
                               netsnmp_agent_request_info *reqinfo,
289
                               netsnmp_request_info *requests)
290
0
{
291
0
    netsnmp_watcher_info  *winfo = (netsnmp_watcher_info *) handler->myvoid;
292
0
#ifndef NETSNMP_NO_WRITE_SUPPORT
293
0
    netsnmp_watcher_cache *old_data;
294
0
#endif /* NETSNMP_NO_WRITE_SUPPORT */
295
296
0
    DEBUGMSGTL(("helper:watcher", "Got request:  %d\n", reqinfo->mode));
297
0
    DEBUGMSGTL(( "helper:watcher", "  oid:"));
298
0
    DEBUGMSGOID(("helper:watcher", requests->requestvb->name,
299
0
                                   requests->requestvb->name_length));
300
0
    DEBUGMSG((   "helper:watcher", "\n"));
301
302
0
    switch (reqinfo->mode) {
303
        /*
304
         * data requests 
305
         */
306
0
    case MODE_GET:
307
0
        snmp_set_var_typed_value(requests->requestvb,
308
0
                                 winfo->type,
309
0
                                 winfo->data,
310
0
                                 get_data_size(winfo));
311
0
        break;
312
313
        /*
314
         * SET requests.  Should only get here if registered RWRITE 
315
         */
316
0
#ifndef NETSNMP_NO_WRITE_SUPPORT
317
0
    case MODE_SET_RESERVE1:
318
0
        if (requests->requestvb->type != winfo->type) {
319
0
            netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_WRONGTYPE);
320
0
            handler->flags |= MIB_HANDLER_AUTO_NEXT_OVERRIDE_ONCE;
321
0
        } else if (((winfo->flags & WATCHER_MAX_SIZE) &&
322
0
                     requests->requestvb->val_len > winfo->max_size) ||
323
0
            ((winfo->flags & WATCHER_FIXED_SIZE) &&
324
0
                requests->requestvb->val_len != get_data_size(winfo))) {
325
0
            netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_WRONGLENGTH);
326
0
            handler->flags |= MIB_HANDLER_AUTO_NEXT_OVERRIDE_ONCE;
327
0
        } else if ((winfo->flags & WATCHER_SIZE_STRLEN) &&
328
0
            (memchr(requests->requestvb->val.string, '\0',
329
0
                requests->requestvb->val_len) != NULL)) {
330
0
            netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_WRONGVALUE);
331
0
            handler->flags |= MIB_HANDLER_AUTO_NEXT_OVERRIDE_ONCE;
332
0
        }
333
0
        break;
334
335
0
    case MODE_SET_RESERVE2:
336
        /*
337
         * store old info for undo later 
338
         */
339
0
        old_data =
340
0
            netsnmp_watcher_cache_create(winfo->data, get_data_size(winfo));
341
0
        if (old_data == NULL) {
342
0
            netsnmp_set_request_error(reqinfo, requests,
343
0
                                      SNMP_ERR_RESOURCEUNAVAILABLE);
344
0
            handler->flags |= MIB_HANDLER_AUTO_NEXT_OVERRIDE_ONCE;
345
0
        } else
346
0
            netsnmp_request_add_list_data(requests,
347
0
                                          netsnmp_create_data_list
348
0
                                          ("watcher", old_data, &free_wrapper));
349
0
        break;
350
351
0
    case MODE_SET_FREE:
352
        /*
353
         * nothing to do 
354
         */
355
0
        break;
356
357
0
    case MODE_SET_ACTION:
358
        /*
359
         * update current 
360
         */
361
0
        set_data(winfo, (void *)requests->requestvb->val.string,
362
0
                                requests->requestvb->val_len);
363
0
        break;
364
365
0
    case MODE_SET_UNDO:
366
0
        old_data = (netsnmp_watcher_cache*)netsnmp_request_get_list_data(requests, "watcher");
367
0
        set_data(winfo, old_data->data, old_data->size);
368
0
        break;
369
370
0
    case MODE_SET_COMMIT:
371
0
        break;
372
0
#endif /* NETSNMP_NO_WRITE_SUPPORT */
373
374
0
    default:
375
0
        snmp_log(LOG_ERR, "watcher handler called with an unknown mode: %d\n",
376
0
                 reqinfo->mode);
377
0
        return SNMP_ERR_GENERR;
378
379
0
    }
380
381
    /* next handler called automatically - 'AUTO_NEXT' */
382
0
    return SNMP_ERR_NOERROR;
383
0
}
384
385
386
    /***************************
387
     *
388
     * A specialised form of the above, reporting
389
     *   the sysUpTime indicated by a given timestamp
390
     *
391
     ***************************/
392
393
netsnmp_mib_handler *
394
netsnmp_get_watched_timestamp_handler(void)
395
0
{
396
0
    netsnmp_mib_handler *ret = NULL;
397
    
398
0
    ret = netsnmp_create_handler("watcher-timestamp",
399
0
                                 netsnmp_watched_timestamp_handler);
400
0
    if (ret) {
401
0
        ret->flags |= MIB_HANDLER_AUTO_NEXT;
402
0
    }
403
0
    return ret;
404
0
}
405
406
int
407
netsnmp_watched_timestamp_register(netsnmp_mib_handler *whandler,
408
                                   netsnmp_handler_registration *reginfo,
409
                                   marker_t timestamp)
410
0
{
411
0
    if (reginfo && whandler && timestamp) {
412
0
        whandler->myvoid = (void *)timestamp;
413
0
        if (netsnmp_inject_handler(reginfo, whandler) == SNMPERR_SUCCESS)
414
0
            return netsnmp_register_scalar(reginfo);   /* XXX - or instance? */
415
0
    }
416
417
0
    snmp_log(LOG_ERR, "could not create watched timestamp handler\n");
418
0
    netsnmp_handler_registration_free(reginfo);
419
420
0
    return MIB_REGISTRATION_FAILED;
421
0
}
422
423
#ifndef NETSNMP_FEATURE_REMOVE_WATCHER_REGISTER_TIMESTAMP
424
int
425
netsnmp_register_watched_timestamp(netsnmp_handler_registration *reginfo,
426
                                   marker_t timestamp)
427
0
{
428
0
    netsnmp_mib_handler *whandler;
429
430
0
    whandler         = netsnmp_get_watched_timestamp_handler();
431
432
0
    return netsnmp_watched_timestamp_register(whandler, reginfo, timestamp);
433
0
}
434
#endif /* NETSNMP_FEATURE_REMOVE_WATCHER_REGISTER_TIMESTAMP */
435
436
437
int
438
netsnmp_watched_timestamp_handler(netsnmp_mib_handler *handler,
439
                               netsnmp_handler_registration *reginfo,
440
                               netsnmp_agent_request_info *reqinfo,
441
                               netsnmp_request_info *requests)
442
0
{
443
0
    marker_t timestamp = (marker_t) handler->myvoid;
444
0
    long     uptime;
445
446
0
    DEBUGMSGTL(("helper:watcher:timestamp",
447
0
                               "Got request:  %d\n", reqinfo->mode));
448
0
    DEBUGMSGTL(( "helper:watcher:timestamp", "  oid:"));
449
0
    DEBUGMSGOID(("helper:watcher:timestamp", requests->requestvb->name,
450
0
                                   requests->requestvb->name_length));
451
0
    DEBUGMSG((   "helper:watcher:timestamp", "\n"));
452
453
0
    switch (reqinfo->mode) {
454
        /*
455
         * data requests 
456
         */
457
0
    case MODE_GET:
458
0
        if (handler->flags & NETSNMP_WATCHER_DIRECT)
459
0
            uptime = * (long*)timestamp;
460
0
        else
461
0
            uptime = netsnmp_marker_uptime( timestamp );
462
0
        snmp_set_var_typed_value(requests->requestvb,
463
0
                                 ASN_TIMETICKS,
464
0
                                 (u_char *) &uptime,
465
0
                                 sizeof(uptime));
466
0
        break;
467
468
        /*
469
         * Timestamps are inherently Read-Only,
470
         *  so don't need to support SET requests.
471
         */
472
0
#ifndef NETSNMP_NO_WRITE_SUPPORT
473
0
    case MODE_SET_RESERVE1:
474
0
        netsnmp_set_request_error(reqinfo, requests,
475
0
                                  SNMP_ERR_NOTWRITABLE);
476
0
        handler->flags |= MIB_HANDLER_AUTO_NEXT_OVERRIDE_ONCE;
477
0
        return SNMP_ERR_NOTWRITABLE;
478
0
#endif /* NETSNMP_NO_WRITE_SUPPORT */
479
0
    }
480
481
    /* next handler called automatically - 'AUTO_NEXT' */
482
0
    return SNMP_ERR_NOERROR;
483
0
}
484
485
    /***************************
486
     *
487
     * Another specialised form of the above,
488
     *   implementing a 'TestAndIncr' spinlock
489
     *
490
     ***************************/
491
492
#ifndef NETSNMP_FEATURE_REMOVE_WATCHER_SPINLOCK
493
494
netsnmp_mib_handler *
495
netsnmp_get_watched_spinlock_handler(void)
496
0
{
497
0
    netsnmp_mib_handler *ret = NULL;
498
    
499
0
    ret = netsnmp_create_handler("watcher-spinlock",
500
0
                                 netsnmp_watched_spinlock_handler);
501
0
    if (ret) {
502
0
        ret->flags |= MIB_HANDLER_AUTO_NEXT;
503
0
    }
504
0
    return ret;
505
0
}
506
507
int
508
netsnmp_register_watched_spinlock(netsnmp_handler_registration *reginfo,
509
                                   int *spinlock)
510
0
{
511
0
    netsnmp_mib_handler  *whandler = NULL;
512
0
    netsnmp_watcher_info *winfo = NULL;
513
514
0
    if (reginfo && spinlock) {
515
0
        whandler = netsnmp_get_watched_spinlock_handler();
516
0
        if (whandler) {
517
0
            whandler->myvoid = (void *)spinlock;
518
0
            winfo = netsnmp_create_watcher_info((void *)spinlock, sizeof(int),
519
0
                                                ASN_INTEGER,
520
0
                                                WATCHER_FIXED_SIZE);
521
0
            if (winfo &&
522
0
                (netsnmp_inject_handler(reginfo, whandler) == SNMPERR_SUCCESS))
523
0
                return netsnmp_register_watched_scalar2(reginfo, winfo);
524
0
        }
525
0
    }
526
527
0
    snmp_log(LOG_ERR, "could not create watched spinlock handler\n");
528
0
    SNMP_FREE(winfo);
529
0
    netsnmp_handler_free(whandler);
530
0
    netsnmp_handler_registration_free(reginfo);
531
532
0
    return MIB_REGISTRATION_FAILED;
533
0
}
534
535
536
int
537
netsnmp_watched_spinlock_handler(netsnmp_mib_handler *handler,
538
                               netsnmp_handler_registration *reginfo,
539
                               netsnmp_agent_request_info *reqinfo,
540
                               netsnmp_request_info *requests)
541
0
{
542
0
#ifndef NETSNMP_NO_WRITE_SUPPORT
543
0
    int     *spinlock = (int *) handler->myvoid;
544
0
    netsnmp_request_info *request;
545
0
#endif /* NETSNMP_NO_WRITE_SUPPORT */
546
547
0
    DEBUGMSGTL(("helper:watcher:spinlock",
548
0
                               "Got request:  %d\n", reqinfo->mode));
549
0
    DEBUGMSGTL(( "helper:watcher:spinlock", "  oid:"));
550
0
    DEBUGMSGOID(("helper:watcher:spinlock", requests->requestvb->name,
551
0
                                   requests->requestvb->name_length));
552
0
    DEBUGMSG((   "helper:watcher:spinlock", "\n"));
553
554
0
    switch (reqinfo->mode) {
555
        /*
556
         * Ensure the assigned value matches the current one
557
         */
558
0
#ifndef NETSNMP_NO_WRITE_SUPPORT
559
0
    case MODE_SET_RESERVE1:
560
0
        for (request=requests; request; request=request->next) {
561
0
            if (request->processed)
562
0
                continue;
563
564
0
            if (*request->requestvb->val.integer != *spinlock) {
565
0
                netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_WRONGVALUE);
566
0
                handler->flags |= MIB_HANDLER_AUTO_NEXT_OVERRIDE_ONCE;
567
0
                return SNMP_ERR_WRONGVALUE;
568
569
0
            }
570
0
        }
571
0
        break;
572
573
        /*
574
         * Everything else worked, so increment the spinlock
575
         */
576
0
    case MODE_SET_COMMIT:
577
0
  (*spinlock)++;
578
0
  break;
579
0
#endif /* NETSNMP_NO_WRITE_SUPPORT */
580
0
    }
581
582
    /* next handler called automatically - 'AUTO_NEXT' */
583
0
    return SNMP_ERR_NOERROR;
584
0
}
585
#endif /* NETSNMP_FEATURE_REMOVE_WATCHER_SPINLOCK */
586
587
    /***************************
588
     *
589
     *   Convenience registration routines - modeled on
590
     *   the equivalent netsnmp_register_*_instance() calls
591
     *
592
     ***************************/
593
594
void *
595
netsnmp_clone_watcher_info(void *p)
596
0
{
597
0
    netsnmp_watcher_info *winfo = p;
598
0
    netsnmp_watcher_info *copy = malloc(sizeof(*copy));
599
600
0
    if (copy)
601
0
  *copy = *winfo;
602
0
    return copy;
603
0
}
604
605
static int
606
register_scalar_watcher(const char* name,
607
                        const oid* reg_oid, size_t reg_oid_len,
608
                        void *data, size_t size, u_char type,
609
                        Netsnmp_Node_Handler * subhandler, int mode)
610
0
{
611
0
    netsnmp_handler_registration *reginfo = NULL;
612
0
    netsnmp_mib_handler *whandler = NULL;
613
0
    netsnmp_watcher_info* watchinfo;
614
615
0
    if (!name || !reg_oid || !data)
616
0
        return MIB_REGISTRATION_FAILED;
617
618
0
    watchinfo = netsnmp_create_watcher_info(data, size, type,
619
0
                                            WATCHER_FIXED_SIZE);
620
0
    if (watchinfo) {
621
0
        whandler = netsnmp_get_watcher_handler();
622
0
        if (whandler) {
623
0
            whandler->myvoid = watchinfo;
624
0
            netsnmp_owns_watcher_info(whandler);
625
0
            reginfo =
626
0
                netsnmp_create_handler_registration(name, subhandler,
627
0
                                                    reg_oid, reg_oid_len,
628
0
                                                    mode);
629
0
            if (reginfo &&
630
0
                (netsnmp_inject_handler(reginfo, whandler) == SNMPERR_SUCCESS))
631
0
                return netsnmp_register_scalar(reginfo);
632
0
        }
633
0
    }
634
635
0
    snmp_log(LOG_ERR, "failed to register scalar watcher\n");
636
0
    netsnmp_handler_free(whandler);
637
0
    SNMP_FREE(watchinfo);
638
0
    netsnmp_handler_registration_free(reginfo);
639
640
0
    return MIB_REGISTRATION_FAILED;
641
0
}
642
643
#ifndef NETSNMP_FEATURE_REMOVE_WATCHER_ULONG_SCALAR
644
int
645
netsnmp_register_ulong_scalar(const char *name,
646
                              const oid * reg_oid, size_t reg_oid_len,
647
                              u_long * it,
648
                              Netsnmp_Node_Handler * subhandler)
649
0
{
650
0
    return register_scalar_watcher(
651
0
        name, reg_oid, reg_oid_len,
652
0
        (void *)it, sizeof( u_long ),
653
0
        ASN_UNSIGNED, subhandler, HANDLER_CAN_RWRITE);
654
0
}
655
#endif /* NETSNMP_FEATURE_REMOVE_WATCHER_ULONG_SCALAR */
656
657
#ifndef NETSNMP_FEATURE_REMOVE_WATCHER_READ_ONLY_ULONG_SCALAR
658
int
659
netsnmp_register_read_only_ulong_scalar(const char *name,
660
                              const oid * reg_oid, size_t reg_oid_len,
661
                              u_long * it,
662
                              Netsnmp_Node_Handler * subhandler)
663
0
{
664
0
    return register_scalar_watcher(
665
0
        name, reg_oid, reg_oid_len,
666
0
        (void *)it, sizeof( u_long ),
667
0
        ASN_UNSIGNED, subhandler, HANDLER_CAN_RONLY);
668
0
}
669
#endif /* NETSNMP_FEATURE_REMOVE_WATCHER_READ_ONLY_ULONG_SCALAR */
670
671
#ifndef NETSNMP_FEATURE_REMOVE_WATCHER_LONG_SCALAR
672
int
673
netsnmp_register_long_scalar(const char *name,
674
                              const oid * reg_oid, size_t reg_oid_len,
675
                              long * it,
676
                              Netsnmp_Node_Handler * subhandler)
677
0
{
678
0
    return register_scalar_watcher(
679
0
        name, reg_oid, reg_oid_len,
680
0
        (void *)it, sizeof( long ),
681
0
        ASN_INTEGER, subhandler, HANDLER_CAN_RWRITE);
682
0
}
683
#endif /* NETSNMP_FEATURE_REMOVE_WATCHER_LONG_SCALAR */
684
685
#ifndef NETSNMP_FEATURE_REMOVE_WATCHER_READ_ONLY_LONG_SCALAR
686
int
687
netsnmp_register_read_only_long_scalar(const char *name,
688
                              const oid * reg_oid, size_t reg_oid_len,
689
                              long * it,
690
                              Netsnmp_Node_Handler * subhandler)
691
0
{
692
0
    return register_scalar_watcher(
693
0
        name, reg_oid, reg_oid_len,
694
0
        (void *)it, sizeof( long ),
695
0
        ASN_INTEGER, subhandler, HANDLER_CAN_RONLY);
696
0
}
697
#endif /* NETSNMP_FEATURE_REMOVE_WATCHER_READ_ONLY_LONG_SCALAR */
698
699
700
#ifndef NETSNMP_FEATURE_REMOVE_WATCHER_INT_SCALAR
701
int
702
netsnmp_register_int_scalar(const char *name,
703
                              const oid * reg_oid, size_t reg_oid_len,
704
                              int * it,
705
                              Netsnmp_Node_Handler * subhandler)
706
0
{
707
0
    return register_scalar_watcher(
708
0
        name, reg_oid, reg_oid_len,
709
0
        (void *)it, sizeof( int ),
710
0
        ASN_INTEGER, subhandler, HANDLER_CAN_RWRITE);
711
0
}
712
#endif /* NETSNMP_FEATURE_REMOVE_WATCHER_INT_SCALAR */
713
714
#ifndef NETSNMP_FEATURE_REMOVE_WATCHER_READ_ONLY_INT_SCALAR
715
int
716
netsnmp_register_read_only_int_scalar(const char *name,
717
                              const oid * reg_oid, size_t reg_oid_len,
718
                              int * it,
719
                              Netsnmp_Node_Handler * subhandler)
720
0
{
721
0
    return register_scalar_watcher(
722
0
        name, reg_oid, reg_oid_len,
723
0
        (void *)it, sizeof( int ),
724
0
        ASN_INTEGER, subhandler, HANDLER_CAN_RONLY);
725
0
}
726
#endif /* NETSNMP_FEATURE_REMOVE_WATCHER_READ_ONLY_INT_SCALAR */
727
728
#ifndef NETSNMP_FEATURE_REMOVE_READ_ONLY_COUNTER32_SCALAR
729
int
730
netsnmp_register_read_only_counter32_scalar(const char *name,
731
                              const oid * reg_oid, size_t reg_oid_len,
732
                              u_long * it,
733
                              Netsnmp_Node_Handler * subhandler)
734
0
{
735
0
    return register_scalar_watcher(
736
0
        name, reg_oid, reg_oid_len,
737
0
        (void *)it, sizeof( u_long ),
738
0
        ASN_COUNTER, subhandler, HANDLER_CAN_RONLY);
739
0
}
740
#endif /* NETSNMP_FEATURE_REMOVE_READ_ONLY_COUNTER32_SCALAR */
741
/**  @} */
742