blob: e543f57bd8bec648070af662b5b1712e319c4c84 [file] [log] [blame]
#include <net-snmp/net-snmp-config.h>
#include <sys/types.h>
#include <net-snmp/net-snmp-includes.h>
#include <net-snmp/agent/net-snmp-agent-includes.h>
#include <net-snmp/agent/multiplexer.h>
/** @defgroup multiplexer multiplexer
* Splits mode requests into calls to different handlers.
* @ingroup utilities
* The multiplexer helper lets you split the calling chain depending
* on the calling mode (get vs getnext vs set). Useful if you want
* different routines to handle different aspects of SNMP requests,
* which is very common for GET vs SET type actions.
*
* Functionally:
*
* -# GET requests call the get_method
* -# GETNEXT requests call the getnext_method, or if not present, the
* get_method.
* -# GETBULK requests call the getbulk_method, or if not present, the
* getnext_method, or if even that isn't present the get_method.
* -# SET requests call the set_method, or if not present return a
* SNMP_ERR_NOTWRITABLE error.
* @{
*/
/** returns a multiplixer handler given a netsnmp_mib_handler_methods structure of subhandlers.
*/
netsnmp_mib_handler *
netsnmp_get_multiplexer_handler(netsnmp_mib_handler_methods *req)
{
netsnmp_mib_handler *ret = NULL;
if (!req) {
snmp_log(LOG_INFO,
"netsnmp_get_multiplexer_handler(NULL) called\n");
return NULL;
}
ret =
netsnmp_create_handler("multiplexer",
netsnmp_multiplexer_helper_handler);
if (ret) {
ret->myvoid = (void *) req;
}
return ret;
}
/** implements the multiplexer helper */
int
netsnmp_multiplexer_helper_handler(netsnmp_mib_handler *handler,
netsnmp_handler_registration *reginfo,
netsnmp_agent_request_info *reqinfo,
netsnmp_request_info *requests)
{
netsnmp_mib_handler_methods *methods;
if (!handler->myvoid) {
snmp_log(LOG_INFO, "improperly registered multiplexer found\n");
return SNMP_ERR_GENERR;
}
methods = (netsnmp_mib_handler_methods *) handler->myvoid;
switch (reqinfo->mode) {
case MODE_GETBULK:
handler = methods->getbulk_handler;
if (handler)
break;
/* Deliberate fallthrough to use GetNext handler */
case MODE_GETNEXT:
handler = methods->getnext_handler;
if (handler)
break;
/* Deliberate fallthrough to use Get handler */
case MODE_GET:
handler = methods->get_handler;
if (!handler) {
netsnmp_request_set_error_all(requests, SNMP_NOSUCHOBJECT);
}
break;
case MODE_SET_RESERVE1:
case MODE_SET_RESERVE2:
case MODE_SET_ACTION:
case MODE_SET_COMMIT:
case MODE_SET_FREE:
case MODE_SET_UNDO:
handler = methods->set_handler;
if (!handler) {
netsnmp_request_set_error_all(requests, SNMP_ERR_NOTWRITABLE);
return SNMP_ERR_NOERROR;
}
break;
/*
* XXX: process SETs specially, and possibly others
*/
default:
snmp_log(LOG_ERR, "unsupported mode for multiplexer: %d\n",
reqinfo->mode);
return SNMP_ERR_GENERR;
}
if (!handler) {
snmp_log(LOG_ERR,
"No handler enabled for mode %d in multiplexer\n",
reqinfo->mode);
return SNMP_ERR_GENERR;
}
return netsnmp_call_handler(handler, reginfo, reqinfo, requests);
}
/** @} */