741 lines
24 KiB
C
741 lines
24 KiB
C
/*
|
|
* Portions of this file are subject to the following copyright(s). See
|
|
* the Net-SNMP's COPYING file for more details and other copyrights
|
|
* that may apply:
|
|
*
|
|
* Portions of this file are copyrighted by:
|
|
* Copyright (c) 2016 VMware, Inc. All rights reserved.
|
|
* Use is subject to license terms specified in the COPYING file
|
|
* distributed with the Net-SNMP package.
|
|
*/
|
|
|
|
#include <net-snmp/net-snmp-config.h>
|
|
#include <net-snmp/net-snmp-features.h>
|
|
|
|
#include <net-snmp/net-snmp-includes.h>
|
|
#include <net-snmp/agent/net-snmp-agent-includes.h>
|
|
|
|
#include <net-snmp/agent/watcher.h>
|
|
|
|
#include <net-snmp/agent/instance.h>
|
|
#include <net-snmp/agent/scalar.h>
|
|
|
|
#include <string.h>
|
|
|
|
#ifdef HAVE_DMALLOC_H
|
|
static void free_wrapper(void * p)
|
|
{
|
|
free(p);
|
|
}
|
|
#else
|
|
#define free_wrapper free
|
|
#endif
|
|
|
|
netsnmp_feature_provide(watcher_all)
|
|
netsnmp_feature_child_of(watcher_all, mib_helpers)
|
|
netsnmp_feature_child_of(watcher_create_info6, watcher_all)
|
|
netsnmp_feature_child_of(watcher_register_timestamp, watcher_all)
|
|
netsnmp_feature_child_of(watcher_ulong_scalar, watcher_all)
|
|
netsnmp_feature_child_of(watcher_read_only_ulong_scalar, watcher_all)
|
|
netsnmp_feature_child_of(watcher_read_only_int_scalar, watcher_all)
|
|
netsnmp_feature_child_of(watcher_long_scalar, watcher_all)
|
|
netsnmp_feature_child_of(watcher_read_only_long_scalar, watcher_all)
|
|
netsnmp_feature_child_of(watcher_int_scalar, watcher_all)
|
|
netsnmp_feature_child_of(read_only_counter32_scalar, watcher_all)
|
|
netsnmp_feature_child_of(watcher_spinlock, watcher_all)
|
|
|
|
/** @defgroup watcher watcher
|
|
* Watch a specified variable and process it as an instance or scalar object
|
|
* @ingroup leaf
|
|
* @{
|
|
*/
|
|
netsnmp_mib_handler *
|
|
netsnmp_get_watcher_handler(void)
|
|
{
|
|
netsnmp_mib_handler *ret = NULL;
|
|
|
|
ret = netsnmp_create_handler("watcher",
|
|
netsnmp_watcher_helper_handler);
|
|
if (ret) {
|
|
ret->flags |= MIB_HANDLER_AUTO_NEXT;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
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)
|
|
{
|
|
winfo->data = data;
|
|
winfo->data_size = size;
|
|
winfo->max_size = max_size;
|
|
winfo->type = type;
|
|
winfo->flags = flags;
|
|
winfo->data_size_p = size_p;
|
|
return winfo;
|
|
}
|
|
|
|
#ifndef NETSNMP_FEATURE_REMOVE_WATCHER_CREATE_INFO6
|
|
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)
|
|
{
|
|
netsnmp_watcher_info *winfo = SNMP_MALLOC_TYPEDEF(netsnmp_watcher_info);
|
|
if (winfo)
|
|
netsnmp_init_watcher_info6(winfo, data, size, type, flags, max_size,
|
|
size_p);
|
|
return winfo;
|
|
}
|
|
#endif /* NETSNMP_FEATURE_REMOVE_WATCHER_CREATE_INFO6 */
|
|
|
|
netsnmp_watcher_info *
|
|
netsnmp_init_watcher_info(netsnmp_watcher_info *winfo,
|
|
void *data, size_t size, u_char type, int flags)
|
|
{
|
|
return netsnmp_init_watcher_info6(winfo, data, size,
|
|
type, (flags ? flags : WATCHER_FIXED_SIZE),
|
|
size, /* Probably wrong for non-fixed
|
|
* size data */
|
|
NULL);
|
|
}
|
|
|
|
netsnmp_watcher_info *
|
|
netsnmp_create_watcher_info(void *data, size_t size, u_char type, int flags)
|
|
{
|
|
netsnmp_watcher_info *winfo = SNMP_MALLOC_TYPEDEF(netsnmp_watcher_info);
|
|
if (winfo)
|
|
netsnmp_init_watcher_info(winfo, data, size, type, flags);
|
|
return winfo;
|
|
}
|
|
|
|
/**
|
|
* Register a watched scalar. The caller remains the owner of watchinfo.
|
|
*
|
|
* @see netsnmp_register_watched_instance2()
|
|
*/
|
|
int
|
|
netsnmp_register_watched_instance(netsnmp_handler_registration *reginfo,
|
|
netsnmp_watcher_info *watchinfo)
|
|
{
|
|
netsnmp_mib_handler *whandler = NULL;
|
|
|
|
if (reginfo && watchinfo) {
|
|
whandler = netsnmp_get_watcher_handler();
|
|
if (whandler) {
|
|
whandler->myvoid = (void *)watchinfo;
|
|
if (netsnmp_inject_handler(reginfo, whandler) == SNMPERR_SUCCESS)
|
|
return netsnmp_register_instance(reginfo);
|
|
}
|
|
}
|
|
|
|
snmp_log(LOG_ERR, "could not create watched instance handler\n");
|
|
netsnmp_handler_free(whandler);
|
|
netsnmp_handler_registration_free(reginfo);
|
|
|
|
return MIB_REGISTRATION_FAILED;
|
|
}
|
|
|
|
/**
|
|
* Register a watched scalar. Ownership of watchinfo is transferred to the handler.
|
|
*
|
|
* @see netsnmp_register_watched_instance()
|
|
*/
|
|
int
|
|
netsnmp_register_watched_instance2(netsnmp_handler_registration *reginfo,
|
|
netsnmp_watcher_info *watchinfo)
|
|
{
|
|
netsnmp_mib_handler *whandler = NULL;
|
|
|
|
if (reginfo && watchinfo) {
|
|
whandler = netsnmp_get_watcher_handler();
|
|
if (whandler) {
|
|
whandler->myvoid = (void *)watchinfo;
|
|
netsnmp_owns_watcher_info(whandler);
|
|
if (netsnmp_inject_handler(reginfo, whandler) == SNMPERR_SUCCESS)
|
|
return netsnmp_register_instance(reginfo);
|
|
}
|
|
}
|
|
|
|
snmp_log(LOG_ERR, "could not create watched instance2 handler\n");
|
|
netsnmp_handler_free(whandler);
|
|
netsnmp_handler_registration_free(reginfo);
|
|
|
|
return MIB_REGISTRATION_FAILED;
|
|
}
|
|
|
|
/**
|
|
* Register a watched scalar. The caller remains the owner of watchinfo.
|
|
*
|
|
* @see netsnmp_register_watched_scalar2()
|
|
*/
|
|
int
|
|
netsnmp_register_watched_scalar(netsnmp_handler_registration *reginfo,
|
|
netsnmp_watcher_info *watchinfo)
|
|
{
|
|
netsnmp_mib_handler *whandler = NULL;
|
|
|
|
if (reginfo && watchinfo) {
|
|
whandler = netsnmp_get_watcher_handler();
|
|
if (whandler) {
|
|
whandler->myvoid = (void *)watchinfo;
|
|
if (netsnmp_inject_handler(reginfo, whandler) == SNMPERR_SUCCESS)
|
|
return netsnmp_register_scalar(reginfo);
|
|
}
|
|
}
|
|
|
|
snmp_log(LOG_ERR, "could not create watched scalar handler\n");
|
|
netsnmp_handler_free(whandler);
|
|
netsnmp_handler_registration_free(reginfo);
|
|
|
|
return MIB_REGISTRATION_FAILED;
|
|
}
|
|
|
|
/**
|
|
* Register a watched scalar. Ownership of watchinfo is transferred to the handler.
|
|
*
|
|
* @see netsnmp_register_watched_scalar()
|
|
*/
|
|
int
|
|
netsnmp_register_watched_scalar2(netsnmp_handler_registration *reginfo,
|
|
netsnmp_watcher_info *watchinfo)
|
|
{
|
|
netsnmp_mib_handler *whandler = NULL;
|
|
|
|
if (reginfo && watchinfo) {
|
|
whandler = netsnmp_get_watcher_handler();
|
|
if (whandler) {
|
|
whandler->myvoid = (void *)watchinfo;
|
|
netsnmp_owns_watcher_info(whandler);
|
|
if (netsnmp_inject_handler(reginfo, whandler) == SNMPERR_SUCCESS)
|
|
return netsnmp_register_scalar(reginfo);
|
|
}
|
|
}
|
|
|
|
snmp_log(LOG_ERR, "could not create watched scalar2 handler\n");
|
|
netsnmp_handler_free(whandler);
|
|
netsnmp_handler_registration_free(reginfo);
|
|
|
|
return MIB_REGISTRATION_FAILED;
|
|
}
|
|
|
|
void
|
|
netsnmp_owns_watcher_info(netsnmp_mib_handler *handler)
|
|
{
|
|
netsnmp_assert(handler);
|
|
netsnmp_assert(handler->myvoid);
|
|
handler->data_clone = (void *(*)(void *))netsnmp_clone_watcher_info;
|
|
handler->data_free = free;
|
|
}
|
|
|
|
/** @cond */
|
|
|
|
NETSNMP_STATIC_INLINE size_t
|
|
get_data_size(const netsnmp_watcher_info* winfo)
|
|
{
|
|
if (winfo->flags & WATCHER_SIZE_STRLEN)
|
|
return strlen((const char*)winfo->data);
|
|
else {
|
|
size_t res;
|
|
if (winfo->flags & WATCHER_SIZE_IS_PTR)
|
|
res = *winfo->data_size_p;
|
|
else
|
|
res = winfo->data_size;
|
|
if (winfo->flags & WATCHER_SIZE_UNIT_OIDS)
|
|
res *= sizeof(oid);
|
|
return res;
|
|
}
|
|
}
|
|
|
|
NETSNMP_STATIC_INLINE void
|
|
set_data(netsnmp_watcher_info* winfo, void* data, size_t size)
|
|
{
|
|
memcpy(winfo->data, data, size);
|
|
if (winfo->flags & WATCHER_SIZE_STRLEN)
|
|
((char*)winfo->data)[size] = '\0';
|
|
else {
|
|
if (winfo->flags & WATCHER_SIZE_UNIT_OIDS)
|
|
size /= sizeof(oid);
|
|
if (winfo->flags & WATCHER_SIZE_IS_PTR)
|
|
*winfo->data_size_p = size;
|
|
else
|
|
winfo->data_size = size;
|
|
}
|
|
}
|
|
|
|
typedef struct {
|
|
size_t size;
|
|
char data[1];
|
|
} netsnmp_watcher_cache;
|
|
|
|
NETSNMP_STATIC_INLINE netsnmp_watcher_cache*
|
|
netsnmp_watcher_cache_create(const void* data, size_t size)
|
|
{
|
|
netsnmp_watcher_cache *res = (netsnmp_watcher_cache*)
|
|
malloc(sizeof(netsnmp_watcher_cache) + size - 1);
|
|
if (res) {
|
|
res->size = size;
|
|
memcpy(res->data, data, size);
|
|
}
|
|
return res;
|
|
}
|
|
|
|
/** @endcond */
|
|
|
|
int
|
|
netsnmp_watcher_helper_handler(netsnmp_mib_handler *handler,
|
|
netsnmp_handler_registration *reginfo,
|
|
netsnmp_agent_request_info *reqinfo,
|
|
netsnmp_request_info *requests)
|
|
{
|
|
netsnmp_watcher_info *winfo = (netsnmp_watcher_info *) handler->myvoid;
|
|
#ifndef NETSNMP_NO_WRITE_SUPPORT
|
|
netsnmp_watcher_cache *old_data;
|
|
#endif /* NETSNMP_NO_WRITE_SUPPORT */
|
|
|
|
DEBUGMSGTL(("helper:watcher", "Got request: %d\n", reqinfo->mode));
|
|
DEBUGMSGTL(( "helper:watcher", " oid:"));
|
|
DEBUGMSGOID(("helper:watcher", requests->requestvb->name,
|
|
requests->requestvb->name_length));
|
|
DEBUGMSG(( "helper:watcher", "\n"));
|
|
|
|
switch (reqinfo->mode) {
|
|
/*
|
|
* data requests
|
|
*/
|
|
case MODE_GET:
|
|
snmp_set_var_typed_value(requests->requestvb,
|
|
winfo->type,
|
|
winfo->data,
|
|
get_data_size(winfo));
|
|
break;
|
|
|
|
/*
|
|
* SET requests. Should only get here if registered RWRITE
|
|
*/
|
|
#ifndef NETSNMP_NO_WRITE_SUPPORT
|
|
case MODE_SET_RESERVE1:
|
|
if (requests->requestvb->type != winfo->type) {
|
|
netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_WRONGTYPE);
|
|
handler->flags |= MIB_HANDLER_AUTO_NEXT_OVERRIDE_ONCE;
|
|
} else if (((winfo->flags & WATCHER_MAX_SIZE) &&
|
|
requests->requestvb->val_len > winfo->max_size) ||
|
|
((winfo->flags & WATCHER_FIXED_SIZE) &&
|
|
requests->requestvb->val_len != get_data_size(winfo))) {
|
|
netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_WRONGLENGTH);
|
|
handler->flags |= MIB_HANDLER_AUTO_NEXT_OVERRIDE_ONCE;
|
|
} else if ((winfo->flags & WATCHER_SIZE_STRLEN) &&
|
|
(memchr(requests->requestvb->val.string, '\0',
|
|
requests->requestvb->val_len) != NULL)) {
|
|
netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_WRONGVALUE);
|
|
handler->flags |= MIB_HANDLER_AUTO_NEXT_OVERRIDE_ONCE;
|
|
}
|
|
break;
|
|
|
|
case MODE_SET_RESERVE2:
|
|
/*
|
|
* store old info for undo later
|
|
*/
|
|
old_data =
|
|
netsnmp_watcher_cache_create(winfo->data, get_data_size(winfo));
|
|
if (old_data == NULL) {
|
|
netsnmp_set_request_error(reqinfo, requests,
|
|
SNMP_ERR_RESOURCEUNAVAILABLE);
|
|
handler->flags |= MIB_HANDLER_AUTO_NEXT_OVERRIDE_ONCE;
|
|
} else
|
|
netsnmp_request_add_list_data(requests,
|
|
netsnmp_create_data_list
|
|
("watcher", old_data, &free_wrapper));
|
|
break;
|
|
|
|
case MODE_SET_FREE:
|
|
/*
|
|
* nothing to do
|
|
*/
|
|
break;
|
|
|
|
case MODE_SET_ACTION:
|
|
/*
|
|
* update current
|
|
*/
|
|
set_data(winfo, (void *)requests->requestvb->val.string,
|
|
requests->requestvb->val_len);
|
|
break;
|
|
|
|
case MODE_SET_UNDO:
|
|
old_data = (netsnmp_watcher_cache*)netsnmp_request_get_list_data(requests, "watcher");
|
|
set_data(winfo, old_data->data, old_data->size);
|
|
break;
|
|
|
|
case MODE_SET_COMMIT:
|
|
break;
|
|
#endif /* NETSNMP_NO_WRITE_SUPPORT */
|
|
|
|
default:
|
|
snmp_log(LOG_ERR, "watcher handler called with an unknown mode: %d\n",
|
|
reqinfo->mode);
|
|
return SNMP_ERR_GENERR;
|
|
|
|
}
|
|
|
|
/* next handler called automatically - 'AUTO_NEXT' */
|
|
return SNMP_ERR_NOERROR;
|
|
}
|
|
|
|
|
|
/***************************
|
|
*
|
|
* A specialised form of the above, reporting
|
|
* the sysUpTime indicated by a given timestamp
|
|
*
|
|
***************************/
|
|
|
|
netsnmp_mib_handler *
|
|
netsnmp_get_watched_timestamp_handler(void)
|
|
{
|
|
netsnmp_mib_handler *ret = NULL;
|
|
|
|
ret = netsnmp_create_handler("watcher-timestamp",
|
|
netsnmp_watched_timestamp_handler);
|
|
if (ret) {
|
|
ret->flags |= MIB_HANDLER_AUTO_NEXT;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int
|
|
netsnmp_watched_timestamp_register(netsnmp_mib_handler *whandler,
|
|
netsnmp_handler_registration *reginfo,
|
|
marker_t timestamp)
|
|
{
|
|
if (reginfo && whandler && timestamp) {
|
|
whandler->myvoid = (void *)timestamp;
|
|
if (netsnmp_inject_handler(reginfo, whandler) == SNMPERR_SUCCESS)
|
|
return netsnmp_register_scalar(reginfo); /* XXX - or instance? */
|
|
}
|
|
|
|
snmp_log(LOG_ERR, "could not create watched timestamp handler\n");
|
|
netsnmp_handler_registration_free(reginfo);
|
|
|
|
return MIB_REGISTRATION_FAILED;
|
|
}
|
|
|
|
#ifndef NETSNMP_FEATURE_REMOVE_WATCHER_REGISTER_TIMESTAMP
|
|
int
|
|
netsnmp_register_watched_timestamp(netsnmp_handler_registration *reginfo,
|
|
marker_t timestamp)
|
|
{
|
|
netsnmp_mib_handler *whandler;
|
|
|
|
whandler = netsnmp_get_watched_timestamp_handler();
|
|
|
|
return netsnmp_watched_timestamp_register(whandler, reginfo, timestamp);
|
|
}
|
|
#endif /* NETSNMP_FEATURE_REMOVE_WATCHER_REGISTER_TIMESTAMP */
|
|
|
|
|
|
int
|
|
netsnmp_watched_timestamp_handler(netsnmp_mib_handler *handler,
|
|
netsnmp_handler_registration *reginfo,
|
|
netsnmp_agent_request_info *reqinfo,
|
|
netsnmp_request_info *requests)
|
|
{
|
|
marker_t timestamp = (marker_t) handler->myvoid;
|
|
long uptime;
|
|
|
|
DEBUGMSGTL(("helper:watcher:timestamp",
|
|
"Got request: %d\n", reqinfo->mode));
|
|
DEBUGMSGTL(( "helper:watcher:timestamp", " oid:"));
|
|
DEBUGMSGOID(("helper:watcher:timestamp", requests->requestvb->name,
|
|
requests->requestvb->name_length));
|
|
DEBUGMSG(( "helper:watcher:timestamp", "\n"));
|
|
|
|
switch (reqinfo->mode) {
|
|
/*
|
|
* data requests
|
|
*/
|
|
case MODE_GET:
|
|
if (handler->flags & NETSNMP_WATCHER_DIRECT)
|
|
uptime = * (long*)timestamp;
|
|
else
|
|
uptime = netsnmp_marker_uptime( timestamp );
|
|
snmp_set_var_typed_value(requests->requestvb,
|
|
ASN_TIMETICKS,
|
|
(u_char *) &uptime,
|
|
sizeof(uptime));
|
|
break;
|
|
|
|
/*
|
|
* Timestamps are inherently Read-Only,
|
|
* so don't need to support SET requests.
|
|
*/
|
|
#ifndef NETSNMP_NO_WRITE_SUPPORT
|
|
case MODE_SET_RESERVE1:
|
|
netsnmp_set_request_error(reqinfo, requests,
|
|
SNMP_ERR_NOTWRITABLE);
|
|
handler->flags |= MIB_HANDLER_AUTO_NEXT_OVERRIDE_ONCE;
|
|
return SNMP_ERR_NOTWRITABLE;
|
|
#endif /* NETSNMP_NO_WRITE_SUPPORT */
|
|
}
|
|
|
|
/* next handler called automatically - 'AUTO_NEXT' */
|
|
return SNMP_ERR_NOERROR;
|
|
}
|
|
|
|
/***************************
|
|
*
|
|
* Another specialised form of the above,
|
|
* implementing a 'TestAndIncr' spinlock
|
|
*
|
|
***************************/
|
|
|
|
#ifndef NETSNMP_FEATURE_REMOVE_WATCHER_SPINLOCK
|
|
|
|
netsnmp_mib_handler *
|
|
netsnmp_get_watched_spinlock_handler(void)
|
|
{
|
|
netsnmp_mib_handler *ret = NULL;
|
|
|
|
ret = netsnmp_create_handler("watcher-spinlock",
|
|
netsnmp_watched_spinlock_handler);
|
|
if (ret) {
|
|
ret->flags |= MIB_HANDLER_AUTO_NEXT;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int
|
|
netsnmp_register_watched_spinlock(netsnmp_handler_registration *reginfo,
|
|
int *spinlock)
|
|
{
|
|
netsnmp_mib_handler *whandler = NULL;
|
|
netsnmp_watcher_info *winfo = NULL;
|
|
|
|
if (reginfo && spinlock) {
|
|
whandler = netsnmp_get_watched_spinlock_handler();
|
|
if (whandler) {
|
|
whandler->myvoid = (void *)spinlock;
|
|
winfo = netsnmp_create_watcher_info((void *)spinlock, sizeof(int),
|
|
ASN_INTEGER,
|
|
WATCHER_FIXED_SIZE);
|
|
if (winfo &&
|
|
(netsnmp_inject_handler(reginfo, whandler) == SNMPERR_SUCCESS))
|
|
return netsnmp_register_watched_scalar2(reginfo, winfo);
|
|
}
|
|
}
|
|
|
|
snmp_log(LOG_ERR, "could not create watched spinlock handler\n");
|
|
SNMP_FREE(winfo);
|
|
netsnmp_handler_free(whandler);
|
|
netsnmp_handler_registration_free(reginfo);
|
|
|
|
return MIB_REGISTRATION_FAILED;
|
|
}
|
|
|
|
|
|
int
|
|
netsnmp_watched_spinlock_handler(netsnmp_mib_handler *handler,
|
|
netsnmp_handler_registration *reginfo,
|
|
netsnmp_agent_request_info *reqinfo,
|
|
netsnmp_request_info *requests)
|
|
{
|
|
#ifndef NETSNMP_NO_WRITE_SUPPORT
|
|
int *spinlock = (int *) handler->myvoid;
|
|
netsnmp_request_info *request;
|
|
#endif /* NETSNMP_NO_WRITE_SUPPORT */
|
|
|
|
DEBUGMSGTL(("helper:watcher:spinlock",
|
|
"Got request: %d\n", reqinfo->mode));
|
|
DEBUGMSGTL(( "helper:watcher:spinlock", " oid:"));
|
|
DEBUGMSGOID(("helper:watcher:spinlock", requests->requestvb->name,
|
|
requests->requestvb->name_length));
|
|
DEBUGMSG(( "helper:watcher:spinlock", "\n"));
|
|
|
|
switch (reqinfo->mode) {
|
|
/*
|
|
* Ensure the assigned value matches the current one
|
|
*/
|
|
#ifndef NETSNMP_NO_WRITE_SUPPORT
|
|
case MODE_SET_RESERVE1:
|
|
for (request=requests; request; request=request->next) {
|
|
if (request->processed)
|
|
continue;
|
|
|
|
if (*request->requestvb->val.integer != *spinlock) {
|
|
netsnmp_set_request_error(reqinfo, requests, SNMP_ERR_WRONGVALUE);
|
|
handler->flags |= MIB_HANDLER_AUTO_NEXT_OVERRIDE_ONCE;
|
|
return SNMP_ERR_WRONGVALUE;
|
|
|
|
}
|
|
}
|
|
break;
|
|
|
|
/*
|
|
* Everything else worked, so increment the spinlock
|
|
*/
|
|
case MODE_SET_COMMIT:
|
|
(*spinlock)++;
|
|
break;
|
|
#endif /* NETSNMP_NO_WRITE_SUPPORT */
|
|
}
|
|
|
|
/* next handler called automatically - 'AUTO_NEXT' */
|
|
return SNMP_ERR_NOERROR;
|
|
}
|
|
#endif /* NETSNMP_FEATURE_REMOVE_WATCHER_SPINLOCK */
|
|
|
|
/***************************
|
|
*
|
|
* Convenience registration routines - modelled on
|
|
* the equivalent netsnmp_register_*_instance() calls
|
|
*
|
|
***************************/
|
|
|
|
netsnmp_watcher_info *
|
|
netsnmp_clone_watcher_info(netsnmp_watcher_info *winfo)
|
|
{
|
|
netsnmp_watcher_info *copy = malloc(sizeof(*copy));
|
|
if (copy)
|
|
*copy = *winfo;
|
|
return copy;
|
|
}
|
|
|
|
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)
|
|
{
|
|
netsnmp_handler_registration *reginfo = NULL;
|
|
netsnmp_mib_handler *whandler = NULL;
|
|
netsnmp_watcher_info* watchinfo;
|
|
|
|
if (!name || !reg_oid || !data)
|
|
return MIB_REGISTRATION_FAILED;
|
|
|
|
watchinfo = netsnmp_create_watcher_info(data, size, type,
|
|
WATCHER_FIXED_SIZE);
|
|
if (watchinfo) {
|
|
whandler = netsnmp_get_watcher_handler();
|
|
if (whandler) {
|
|
whandler->myvoid = watchinfo;
|
|
netsnmp_owns_watcher_info(whandler);
|
|
reginfo =
|
|
netsnmp_create_handler_registration(name, subhandler,
|
|
reg_oid, reg_oid_len,
|
|
mode);
|
|
if (reginfo &&
|
|
(netsnmp_inject_handler(reginfo, whandler) == SNMPERR_SUCCESS))
|
|
return netsnmp_register_scalar(reginfo);
|
|
}
|
|
}
|
|
|
|
snmp_log(LOG_ERR, "failed to register scalar watcher\n");
|
|
netsnmp_handler_free(whandler);
|
|
SNMP_FREE(watchinfo);
|
|
netsnmp_handler_registration_free(reginfo);
|
|
|
|
return MIB_REGISTRATION_FAILED;
|
|
}
|
|
|
|
#ifndef NETSNMP_FEATURE_REMOVE_WATCHER_ULONG_SCALAR
|
|
int
|
|
netsnmp_register_ulong_scalar(const char *name,
|
|
const oid * reg_oid, size_t reg_oid_len,
|
|
u_long * it,
|
|
Netsnmp_Node_Handler * subhandler)
|
|
{
|
|
return register_scalar_watcher(
|
|
name, reg_oid, reg_oid_len,
|
|
(void *)it, sizeof( u_long ),
|
|
ASN_UNSIGNED, subhandler, HANDLER_CAN_RWRITE);
|
|
}
|
|
#endif /* NETSNMP_FEATURE_REMOVE_WATCHER_ULONG_SCALAR */
|
|
|
|
#ifndef NETSNMP_FEATURE_REMOVE_WATCHER_READ_ONLY_ULONG_SCALAR
|
|
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)
|
|
{
|
|
return register_scalar_watcher(
|
|
name, reg_oid, reg_oid_len,
|
|
(void *)it, sizeof( u_long ),
|
|
ASN_UNSIGNED, subhandler, HANDLER_CAN_RONLY);
|
|
}
|
|
#endif /* NETSNMP_FEATURE_REMOVE_WATCHER_READ_ONLY_ULONG_SCALAR */
|
|
|
|
#ifndef NETSNMP_FEATURE_REMOVE_WATCHER_LONG_SCALAR
|
|
int
|
|
netsnmp_register_long_scalar(const char *name,
|
|
const oid * reg_oid, size_t reg_oid_len,
|
|
long * it,
|
|
Netsnmp_Node_Handler * subhandler)
|
|
{
|
|
return register_scalar_watcher(
|
|
name, reg_oid, reg_oid_len,
|
|
(void *)it, sizeof( long ),
|
|
ASN_INTEGER, subhandler, HANDLER_CAN_RWRITE);
|
|
}
|
|
#endif /* NETSNMP_FEATURE_REMOVE_WATCHER_LONG_SCALAR */
|
|
|
|
#ifndef NETSNMP_FEATURE_REMOVE_WATCHER_READ_ONLY_LONG_SCALAR
|
|
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)
|
|
{
|
|
return register_scalar_watcher(
|
|
name, reg_oid, reg_oid_len,
|
|
(void *)it, sizeof( long ),
|
|
ASN_INTEGER, subhandler, HANDLER_CAN_RONLY);
|
|
}
|
|
#endif /* NETSNMP_FEATURE_REMOVE_WATCHER_READ_ONLY_LONG_SCALAR */
|
|
|
|
|
|
#ifndef NETSNMP_FEATURE_REMOVE_WATCHER_INT_SCALAR
|
|
int
|
|
netsnmp_register_int_scalar(const char *name,
|
|
const oid * reg_oid, size_t reg_oid_len,
|
|
int * it,
|
|
Netsnmp_Node_Handler * subhandler)
|
|
{
|
|
return register_scalar_watcher(
|
|
name, reg_oid, reg_oid_len,
|
|
(void *)it, sizeof( int ),
|
|
ASN_INTEGER, subhandler, HANDLER_CAN_RWRITE);
|
|
}
|
|
#endif /* NETSNMP_FEATURE_REMOVE_WATCHER_INT_SCALAR */
|
|
|
|
#ifndef NETSNMP_FEATURE_REMOVE_WATCHER_READ_ONLY_INT_SCALAR
|
|
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)
|
|
{
|
|
return register_scalar_watcher(
|
|
name, reg_oid, reg_oid_len,
|
|
(void *)it, sizeof( int ),
|
|
ASN_INTEGER, subhandler, HANDLER_CAN_RONLY);
|
|
}
|
|
#endif /* NETSNMP_FEATURE_REMOVE_WATCHER_READ_ONLY_INT_SCALAR */
|
|
|
|
#ifndef NETSNMP_FEATURE_REMOVE_READ_ONLY_COUNTER32_SCALAR
|
|
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)
|
|
{
|
|
return register_scalar_watcher(
|
|
name, reg_oid, reg_oid_len,
|
|
(void *)it, sizeof( u_long ),
|
|
ASN_COUNTER, subhandler, HANDLER_CAN_RONLY);
|
|
}
|
|
#endif /* NETSNMP_FEATURE_REMOVE_READ_ONLY_COUNTER32_SCALAR */
|
|
/** @} */
|
|
|