summaryrefslogtreecommitdiff
path: root/perl/agent/agent.pm
diff options
context:
space:
mode:
Diffstat (limited to 'perl/agent/agent.pm')
-rw-r--r--perl/agent/agent.pm541
1 files changed, 541 insertions, 0 deletions
diff --git a/perl/agent/agent.pm b/perl/agent/agent.pm
new file mode 100644
index 0000000..82ddf20
--- /dev/null
+++ b/perl/agent/agent.pm
@@ -0,0 +1,541 @@
+package NetSNMP::agent;
+
+use strict;
+use warnings;
+use Carp;
+
+require Exporter;
+require DynaLoader;
+use AutoLoader;
+
+use NetSNMP::default_store (':all');
+use NetSNMP::agent::default_store (':all');
+use NetSNMP::OID (':all');
+use NetSNMP::agent::netsnmp_request_infoPtr;
+
+use vars qw(@ISA %EXPORT_TAGS @EXPORT_OK @EXPORT $VERSION $AUTOLOAD);
+
+@ISA = qw(Exporter AutoLoader DynaLoader);
+
+# Items to export into callers namespace by default. Note: do not export
+# names by default without a very good reason. Use EXPORT_OK instead.
+# Do not simply export all your public functions/methods/constants.
+
+# This allows declaration use NetSNMP::agent ':all';
+# If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
+# will save memory.
+%EXPORT_TAGS = ( 'all' => [ qw(
+ MODE_GET
+ MODE_GETBULK
+ MODE_GETNEXT
+ MODE_SET_ACTION
+ MODE_SET_BEGIN
+ MODE_SET_COMMIT
+ MODE_SET_FREE
+ MODE_SET_RESERVE1
+ MODE_SET_RESERVE2
+ MODE_SET_UNDO
+ SNMP_ERR_NOERROR
+ SNMP_ERR_TOOBIG
+ SNMP_ERR_NOSUCHNAME
+ SNMP_ERR_BADVALUE
+ SNMP_ERR_READONLY
+ SNMP_ERR_GENERR
+ SNMP_ERR_NOACCESS
+ SNMP_ERR_WRONGTYPE
+ SNMP_ERR_WRONGLENGTH
+ SNMP_ERR_WRONGENCODING
+ SNMP_ERR_WRONGVALUE
+ SNMP_ERR_NOCREATION
+ SNMP_ERR_INCONSISTENTVALUE
+ SNMP_ERR_RESOURCEUNAVAILABLE
+ SNMP_ERR_COMMITFAILED
+ SNMP_ERR_UNDOFAILED
+ SNMP_ERR_AUTHORIZATIONERROR
+ SNMP_ERR_NOTWRITABLE
+) ] );
+
+@EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
+
+@EXPORT = qw(
+ MODE_GET
+ MODE_GETBULK
+ MODE_GETNEXT
+ MODE_SET_ACTION
+ MODE_SET_BEGIN
+ MODE_SET_COMMIT
+ MODE_SET_FREE
+ MODE_SET_RESERVE1
+ MODE_SET_RESERVE2
+ MODE_SET_UNDO
+ SNMP_ERR_NOERROR
+ SNMP_ERR_TOOBIG
+ SNMP_ERR_NOSUCHNAME
+ SNMP_ERR_BADVALUE
+ SNMP_ERR_READONLY
+ SNMP_ERR_GENERR
+ SNMP_ERR_NOACCESS
+ SNMP_ERR_WRONGTYPE
+ SNMP_ERR_WRONGLENGTH
+ SNMP_ERR_WRONGENCODING
+ SNMP_ERR_WRONGVALUE
+ SNMP_ERR_NOCREATION
+ SNMP_ERR_INCONSISTENTVALUE
+ SNMP_ERR_RESOURCEUNAVAILABLE
+ SNMP_ERR_COMMITFAILED
+ SNMP_ERR_UNDOFAILED
+ SNMP_ERR_AUTHORIZATIONERROR
+ SNMP_ERR_NOTWRITABLE
+);
+$VERSION = '5.0403';
+
+sub AUTOLOAD {
+ # This AUTOLOAD is used to 'autoload' constants from the constant()
+ # XS function. If a constant is not found then control is passed
+ # to the AUTOLOAD in AutoLoader.
+
+ my $constname;
+ ($constname = $AUTOLOAD) =~ s/.*:://;
+ croak "& not defined" if $constname eq 'constant';
+ my $val = constant($constname, @_ ? $_[0] : 0);
+ if ($! != 0) {
+ if ($! =~ /Invalid/ || $!{EINVAL}) {
+ $AutoLoader::AUTOLOAD = $AUTOLOAD;
+ goto &AutoLoader::AUTOLOAD;
+ }
+ else {
+ croak "Your vendor has not defined NetSNMP::agent macro $constname";
+ }
+ }
+ {
+ no strict 'refs';
+ # Fixed between 5.005_53 and 5.005_61
+# if ($] >= 5.00561) {
+# *$AUTOLOAD = sub () { $val };
+# }
+# else {
+ *$AUTOLOAD = sub { $val };
+# }
+ }
+ goto &$AUTOLOAD;
+}
+
+{
+ my $haveinit = 0;
+
+ sub mark_init_agent_done {
+ $haveinit = 1;
+ }
+
+ sub maybe_init_agent {
+ return if ($haveinit);
+ $haveinit = 1;
+
+ snmp_enable_stderrlog();
+ my $flags = $_[0];
+ if ($flags->{'AgentX'}) {
+ netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_ROLE, 1);
+ }
+ init_agent($flags->{'Name'} || "perl");
+ if ($flags->{'Ports'}) {
+ netsnmp_ds_set_string(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_PORTS, $flags->{'Ports'});
+ }
+ init_mib();
+ }
+}
+
+{
+ my $haveinit = 0;
+
+ sub mark_init_lib_done {
+ $haveinit = 1;
+ }
+
+ sub maybe_init_lib {
+ return if ($haveinit);
+ $haveinit = 1;
+
+ my $flags = $_[0];
+ init_snmp($flags->{'Name'} || "perl");
+ if (netsnmp_ds_get_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_ROLE) != 1) {
+ init_master_agent();
+ }
+ }
+}
+
+sub new {
+ my $type = shift;
+ my ($self);
+ %$self = @_;
+ bless($self, $type);
+ if ($self->{'dont_init_agent'}) {
+ $self->mark_init_agent_done();
+ } else {
+ $self->maybe_init_agent();
+ }
+ if ($self->{'dont_init_lib'}) {
+ $self->mark_init_lib_done();
+ }
+ return $self;
+}
+
+sub register($$$$) {
+ my ($self, $name, $oid, $sub) = @_;
+ my $reg = NetSNMP::agent::netsnmp_handler_registration::new($name, $oid, $sub);
+ $reg->register() if ($reg);
+ return $reg;
+}
+
+sub main_loop {
+ my $self = shift;
+ while(1) {
+ $self->agent_check_and_process(1);
+ }
+}
+
+sub agent_check_and_process {
+ my ($self, $blocking) = @_;
+ $self->maybe_init_lib();
+ __agent_check_and_process($blocking || 0);
+}
+
+bootstrap NetSNMP::agent $VERSION;
+
+# Preloaded methods go here.
+
+# Autoload methods go after =cut, and are processed by the autosplit program.
+
+1;
+__END__
+
+=head1 NAME
+
+NetSNMP::agent - Perl extension for the net-snmp agent.
+
+=head1 SYNOPSIS
+
+ use NetSNMP::agent;
+
+ my $agent = new NetSNMP::agent('Name' => 'my_agent_name');
+
+
+=head1 DESCRIPTION
+
+This module implements an API set to make a SNMP agent act as a snmp
+agent, a snmp subagent (using the AgentX subagent protocol) and/or
+embedded perl-APIs directly within the traditional net-snmp agent demon.
+
+Also see the tutorial about the genaral Net-SNMP C API, which this
+module implements in a perl-way, and a perl specific tutorial at:
+
+ http://www.net-snmp.org/tutorial-5/toolkit/
+
+=head1 EXAMPLES
+
+=head2 Sub-agent example
+
+ use NetSNMP::agent (':all');
+ use NetSNMP::ASN qw(ASN_OCTET_STR);
+
+ my $value = "hello world";
+ sub myhandler {
+ my ($handler, $registration_info, $request_info, $requests) = @_;
+ my $request;
+
+ for($request = $requests; $request; $request = $request->next()) {
+ my $oid = $request->getOID();
+ if ($request_info->getMode() == MODE_GET) {
+ # ... generally, you would calculate value from oid
+ if ($oid == new NetSNMP::OID(".1.3.6.1.4.1.8072.9999.9999.7375.1.0")) {
+ $request->setValue(ASN_OCTET_STR, $value);
+ }
+ } elsif ($request_info->getMode() == MODE_GETNEXT) {
+ # ... generally, you would calculate value from oid
+ if ($oid < new NetSNMP::OID(".1.3.6.1.4.1.8072.9999.9999.7375.1.0")) {
+ $request->setOID(".1.3.6.1.4.1.8072.9999.9999.7375.1.0");
+ $request->setValue(ASN_OCTET_STR, $value);
+ }
+ } elsif ($request_info->getMode() == MODE_SET_RESERVE1) {
+ if ($oid != new NetSNMP::OID(".1.3.6.1.4.1.8072.9999.9999.7375.1.0")) { # do error checking here
+ $request->setError($request_info, SNMP_ERR_NOSUCHNAME);
+ }
+ } elsif ($request_info->getMode() == MODE_SET_ACTION) {
+ # ... (or use the value)
+ $value = $request->getValue();
+ }
+ }
+
+ }
+
+ my $agent = new NetSNMP::agent(
+ # makes the agent read a my_agent_name.conf file
+ 'Name' => "my_agent_name",
+ 'AgentX' => 1
+ );
+ $agent->register("my_agent_name", ".1.3.6.1.4.1.8072.9999.9999.7375",
+ \&myhandler);
+
+ my $running = 1;
+ while($running) {
+ $agent->agent_check_and_process(1);
+ }
+
+ $agent->shutdown();
+
+
+=head2 Embedded agent example
+
+ # place this in a .pl file, and then in your snmpd.conf file put:
+ # perl do '/path/to/file.pl';
+
+ use NetSNMP::agent;
+ my $agent;
+
+ sub myhandler {
+ my ($handler, $registration_info, $request_info, $requests) = @_;
+ # ...
+ }
+
+ $agent = new NetSNMP::agent(
+ 'Name' => 'my_agent_name'
+ );
+
+ $agent->register("my_agent_name", ".1.3.6.1.4.1.8072.9999.9999.7375",
+ \&myhandler);
+
+ $agent->main_loop();
+
+
+=head1 CONSTRUCTOR
+
+ new ( OPTIONS )
+ This is the constructor for a new NetSNMP::agent object.
+
+ Possible options are:
+
+ Name - Name of the agent (optional, defaults to "perl")
+ (The snmp library will read a NAME.conf snmp
+ configuration file based on this argument.)
+ AgentX - Make us a sub-agent (0 = false, 1 = true)
+ (The Net-SNMP master agent must be running first)
+ Ports - Ports this agent will listen on (EG: "udp:161,tcp:161")
+
+ Example:
+
+ $agent = new NetSNMP::agent(
+ 'Name' => 'my_agent_name',
+ 'AgentX' => 1
+ );
+
+
+=head1 METHODS
+
+ register (NAME, OID, \&handler_routine )
+ Registers the callback handler with given OID.
+
+ $agent->register();
+
+ A return code of 0 indicates no error.
+
+ agent_check_and_process ( BLOCKING )
+ Run one iteration of the main loop.
+
+ BLOCKING - Blocking or non-blocking call. 1 = true, 0 = false.
+
+ $agent->agent_check_and_process(1);
+
+ main_loop ()
+ Runs the agent in a loop. Does not return.
+
+ shutdown ()
+ Nicely shuts down the agent or sub-agent.
+
+ $agent->shutdown();
+
+=head1 HANDLER CALLBACKS
+
+ handler ( HANDLER, REGISTRATION_INFO, REQUEST_INFO, REQUESTS )
+
+ The handler is called with the following parameters:
+
+ HANDLER - FIXME
+ REGISTRATION_INFO - what are the correct meanings of these?
+ REQUEST_INFO -
+ REQUESTS -
+
+ Example handler:
+
+ sub myhandler {
+ my ($handler, $reg_info, $request_info, $requests) = @_;
+ # ...
+ }
+
+The handler subroutine will be called when a SNMP request received by
+the agent for anything below the registered OID. The handler is
+passed 4 arguments: $handler, $registration_info, $request_info,
+$requests. These match the arguments passed to the C version of the
+same API. Note that they are not entirely complete objects but are
+functional "enough" at this point in time.
+
+=head2 $request_info object functions
+
+ getMode ()
+ Returns the mode of the request. See the MODES section for
+ list of valid modes.
+
+ $mode = $request->getMode();
+
+ getRootOID ()
+ Returns a NetSNMP::OID object that describes the registration
+ point that the handler is getting called for (in case you
+ register one handler function with multiple OIDs, which should
+ be rare anyway)
+
+ $root_oid = $request->getRootOID();
+
+=head2 $request object functions
+
+ next ()
+ Returns the next request in the list or undef if there is no
+ next request.
+
+ $request = $request->next();
+
+ getOID ()
+ Returns the oid of the request (a NetSNMP::OID class).
+
+ $oid = $request->getOID();
+
+ setOID (new NetSNMP::OID("someoid"))
+ Sets the OID of the request to a passed oid value. This
+ should generally only be done during handling of GETNEXT
+ requests.
+
+ $request->setOID(new NetSNMP::OID("someoid"));
+
+ getValue ()
+ Returns the value of the request. Used for example when
+ setting values.
+
+ $value = $request->getValue();
+
+ FIXME: how to get the type of the value? Is it even available?
+ [Wes: no, not yet.]
+
+ setValue ( TYPE, DATA )
+ Sets the data to be returned to the daemon.
+
+ Returns 1 on success, 0 on error.
+
+ TYPE - Type of the data. See NetSNMP::ASN for valid types.
+ DATA - The data to return.
+
+ $ret = $request->setValue(ASN_OCTET_STR, "test");
+
+ setError ( REQUEST_INFO, ERROR_CODE )
+ Sets the given error code for the request. See the ERROR CODES
+ section for list of valid codes.
+
+ $request->setError($request_info, SNMP_ERR_NOTWRITABLE);
+
+ getProcessed ()
+ The processed flag indicates that a request does not need to
+ be dealt with because someone else (a higher handler) has
+ dealt with it already.
+
+ $processed = $request->getProcessed();
+
+ setProcessed ( PROCESSED )
+ Sets the processed flag flag in the request. You generally
+ should not have to set this yourself.
+
+ PROCESSED - 0 = false, 1 = true
+
+ $request->setProcessed(1);
+
+ getDelegated ()
+ If you can handle a request in the background or at a future
+ time (EG, you're waiting on a file handle, or network traffic,
+ or ...), the delegated flag can be set in the request. When
+ the request is processed in the future the flag should be set
+ back to 0 so the agent will know that it can wrap up the
+ original request and send it back to the manager. This has
+ not been tested within perl, but it hopefully should work.
+
+ $delegated = $request->getDelegated();
+
+ setDelegated ( DELEGATED )
+ Sets the delegated flag.
+
+ DELEGATED - 0 = false, 1 = true
+
+ $request->setDelegated(1);
+
+ getRepeat ()
+ The repeat flag indicates that a getbulk operation is being
+ handled and this indicates how many answers need to be
+ returned. Generally, if you didn't register to directly
+ handle getbulk support yourself, you won't need to deal with
+ this value.
+
+ $repeat = $request->getRepeat();
+
+ setRepeat ( REPEAT )
+ Sets the repeat count (decrement after answering requests if
+ you handle getbulk requests yourself)
+
+ REPEAT - repeat count FIXME
+
+ $request->setRepeat(5);
+
+=head1 MODES
+
+ MODE_GET
+ MODE_GETBULK
+ MODE_GETNEXT
+ MODE_SET_ACTION
+ MODE_SET_BEGIN
+ MODE_SET_COMMIT
+ MODE_SET_FREE
+ MODE_SET_RESERVE1
+ MODE_SET_RESERVE2
+ MODE_SET_UNDO
+
+=head1 ERROR CODES
+
+ SNMP_ERR_NOERROR
+ SNMP_ERR_TOOBIG
+ SNMP_ERR_NOSUCHNAME
+ SNMP_ERR_BADVALUE
+ SNMP_ERR_READONLY
+ SNMP_ERR_GENERR
+ SNMP_ERR_NOACCESS
+ SNMP_ERR_WRONGTYPE
+ SNMP_ERR_WRONGLENGTH
+ SNMP_ERR_WRONGENCODING
+ SNMP_ERR_WRONGVALUE
+ SNMP_ERR_NOCREATION
+ SNMP_ERR_INCONSISTENTVALUE
+ SNMP_ERR_RESOURCEUNAVAILABLE
+ SNMP_ERR_COMMITFAILED
+ SNMP_ERR_UNDOFAILED
+ SNMP_ERR_AUTHORIZATIONERROR
+ SNMP_ERR_NOTWRITABLE
+
+=head1 AUTHOR
+
+Please mail the net-snmp-users@lists.sourceforge.net mailing list for
+help, questions or comments about this module.
+
+Module written by:
+ Wes Hardaker <hardaker@users.sourceforge.net>
+
+Documentation written by:
+ Toni Willberg <toniw@iki.fi>
+ Wes Hardaker <hardaker@users.sourceforge.net>
+
+=head1 SEE ALSO
+
+NetSNMP::OID(3), NetSNMP::ASN(3), perl(1).
+
+=cut