diff options
Diffstat (limited to 'perl/agent/agent.pm')
-rw-r--r-- | perl/agent/agent.pm | 541 |
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 |