/*
*
* U.S. Government Rights - Commercial software. Government users are subject
* to the Sun Microsystems, Inc. standard license agreement and applicable
* provisions of the FAR and its supplements.
*
*
* This distribution may include materials developed by third parties. Sun,
* Sun Microsystems, the Sun logo and Solaris are trademarks or registered
* trademarks of Sun Microsystems, Inc. in the U.S. and other countries.
*
*/
/*
* Note: this file originally auto-generated by mib2c using :
* mib2c.scalar.conf,v 1.5 2002/07/18 14:18:52 dts12 Exp $
*/
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#include <time.h>
#include "demo_module_10.h"
// Default scalar data value
static long exampleData = 0;
// Status of data collection
// Default delay time
// Default alarm interval
// Data collection timestamp
/*
The following code example demonstrates a module design that handles
long running data collections so that their values can be polled by
an SNMP manager. The example also shows how to implement objects that
normally would block the agent as it waits for external events in such
a way that the agent can continue responding to other requests while
this implementation waits.
This example uses the following features of SMA:
- Setting the delegated member of the requests structure to 1 to indicate to the
agent that this request should be delayed. The agent queues this request
to be handled later and then is available to handle other requests. The
agent is not blocked by this request.
- Registering an SNMP alarm to update the results at a later time.
- Use of a status variable to communicate the status of a data collection to
the polling SNMP manager.
- Use of a refreshTime variable to return the date and time that the data collection
completed.
*/
/* Initialialization routine that is automatically called by the agent.
The function name must match init_FILENAME() */
void
init_demo_module_10(void)
{
/*
* the OID at which to register the exampleData variable.
*/
{1, 3, 6, 1, 4, 1, 42, 2, 2, 4, 4, 10, 1, 1, 0};
/*
* the OID at which to register the status variable.
*/
{1, 3, 6, 1, 4, 1, 42, 2, 2, 4, 4, 10, 1, 2, 0};
/*
* the OID at which to register the refreshTime variable.
*/
{1, 3, 6, 1, 4, 1, 42, 2, 2, 4, 4, 10, 1, 3, 0};
/*
* A debugging statement. Run the agent with -Ddemo_module_10 to see
* default. Use the -L option to write debugging output to the
* screen.
*/
/*
* Creates a read-only registration handler named longRunScalar,
* which calls the get_longRunScalar function to service snmp
* requests for the longRunScalar_oid object. The OID_LENGTH
* argument calculates the length of the longRunScalar_oid.
*/
("longRunScalar",
/*
* Register the instance and handler.
*
*/
/*
* which calls the get_status function to service snmp
* requests for the status_oid object. The OID_LENGTH
* argument calculates the length of the status_oid.
*/
("delayed_instance_handler",
/*
* Register the instance and handler.
*
*/
/*
* Creates a read-only registration handler named getTimestamp,
* which calls the get_timestamp function to service snmp
* get requests for the timestamp_oid object. The OID_LENGTH
* argument calculates the length of the timestamp_oid.
*/
("getTimestamp",
/*
* Register the instance and handler.
*
*/
}
int
{
/*
This handler is called to handle SNMP GET and SNMP SET
requests for the my_delayed_oid object. If it is called to
handle SNMP GET requests, the handler does not need to
handle a GETNEXT if it is registered as an instance handler.
Instance handlers only deliver one request at a time, so we
do not need to loop over a list of requests. */
/*
* here we merely mention that we'll answer this request
* later. we don't actually care about the mode type in this
* example, but for certain cases you may, so I'll leave in the
* otherwise useless switch and case statements
*/
default:
/*
* Mark this variable as something that cannot be handled now
* by setting the delegated member of the requests structure
* to 1. The agent queues the request to be handled at a later
* time and continues responding to other client requests.
*
*/
/*
* Register an alarm to update the results at a later
* time. Normally, we might have to query something else
* (like an external request sent to a different network
* or system socket, etc), but for this example we'll do
* something really simply and just insert an alarm for a
* certain period of time.
*/
0, /* dont repeat. */
get_status, /* the function */
/* to call */
/*
* Create a "cache" of useful
* information that can be retrieved
* at a later time. This argument is
* passed back to the module in the callback
* function for an alarm.
*/
(void *)
NULL));
break;
}
return SNMP_ERR_NOERROR;
}
int
{
/*
* This handler returns the data from the data collection, if the
* collection has finished. If the collection has not finished.
* it returns an SNMP_ERR_NOACCESS error.
*
* This handler is never called for a getnext if it is registered as
* an instance. An instance handler only delivers one request at a
* time, so we do not need to loop over a list of requests.
*/
case MODE_GET:
// if collection done, return data; else return snmp error
if (status == 2)
sizeof (exampleData) /* length in bytes */);
else
break;
default:
/*
* We should never get here, so this is a really bad error.
*/
return (SNMP_ERR_GENERR);
}
return (SNMP_ERR_NOERROR);
}
int
{
/*
* This handler returns the date and time of the current data
* collection. If the collection has not completed, it returns
* an SNMP_ERR_NOACCESS error.
*
* This handler is never called for a getnext if it is registered as
* an instance. An instance handler only delivers one request at a
* time, so we do not need to loop over a list of requests.
*/
case MODE_GET:
// A data collection is ready. Return its timestamp.
if (status == 2)
sizeof (refreshTime));
else
// no data collection, so no timestamp available.
break;
default:
/*
* We should never get here, so this is a really bad error.
*/
return (SNMP_ERR_GENERR);
}
return (SNMP_ERR_NOERROR);
}
void
{
/*
* This function returns the value of the status variable.
* If the value of status is 0 (no collection is running), it
* calles collect_data to start one.
*
*/
/*
* Extract the cache from the passed argument.
*/
/*
* Make sure the cache created earlier is still
* valid. If not, the request timed out for some reason and we
* do not need to keep processing things. Should never happen, but
* this double checks.
*/
if (!cache) {
return;
}
/*
* Re-establish the previous pointers,
*/
DEBUGMSGTL(("demo_module_10",
"continuing delayed request, mode = %d\n",
/*
* Set delegated to zero to indicate that the request is no longer
* delegated and answer the query.
*/
/*
* Registering as an instance means we do not need to deal with
* GETNEXT processing, so we do not handle it here at all.
*
* However, since the instance handler already reset the mode
* back to GETNEXT from the GET mode, we need to do the
* same thing in both cases.
*
*/
case MODE_GET:
// no collection running, start one.
if (status == 0)
collect_data();
sizeof (status) /* length in bytes */);
break;
case MODE_SET_RESERVE1:
/*
* check type
*/
/*
* If not an integer, return SNMP error.
*/
/*
* Free cache. It is no longer needed.
*/
return;
}
break;
case MODE_SET_RESERVE2:
/*
* Store old value for UNDO support in the future.
*/
/*
* malloc failed
*/
if (delay_time_cache == NULL) {
return;
}
/*
* Add our temporary information to the request itself.
* This is then retrivable later. The free function
* passed auto-frees it when the request is later
* deleted.
*/
delay_time_cache, free));
break;
case MODE_SET_ACTION:
// get status integer from request
// if status == 0, start data collection, else return error
collect_data();
} else
break;
case MODE_SET_UNDO:
/*
* A failure occurred. Reset to the
* previously value by extracting the previosuly
* stored information from the request.
*/
break;
case MODE_SET_COMMIT:
break;
case MODE_SET_FREE:
/*
* The only thing to do here is free the old memdup'ed
* value, but it's auto-freed by the datalist recovery, so
* we don't have anything to actually do here
*/
break;
}
/*
* free the information cache
*/
}
void collect_data()
{
/*
* This function starts a data collection.
*/
// get timestamp for this data collection
exampleData = 325;
return;
}