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