# BRCM_VERSION=3
[bcm963xx.git] / userapps / opensource / net-snmp / perl / SNMP / SNMP.pm
1 # SNMP.pm -- Perl 5 interface to the net-snmp toolkit
2 #
3 # written by G. S. Marzot (gmarzot@nortelnetworks.com)
4 #
5 #     Copyright (c) 1995-2000 G. S. Marzot. All rights reserved.
6 #     This program is free software; you can redistribute it and/or
7 #     modify it under the same terms as Perl itself.
8
9 package SNMP;
10 $VERSION = '5.0.8';   # current release version number
11
12 require Exporter;
13 require DynaLoader;
14 require AutoLoader;
15
16 use NetSNMP::default_store (':all');
17
18 @SNMP::ISA = qw(Exporter AutoLoader DynaLoader);
19 # Items to export into callers namespace by default. Note: do not export
20 # names by default without a very good reason. Use EXPORT_OK instead.
21 # Do not simply export all your public functions/methods/constants.
22 @SNMP::EXPORT = qw(
23         RECEIVED_MESSAGE
24         SNMPERR_BAD_ADDRESS
25         SNMPERR_BAD_LOCPORT
26         SNMPERR_BAD_SESSION
27         SNMPERR_GENERR
28         SNMPERR_TOO_LONG
29         SNMP_DEFAULT_ADDRESS
30         SNMP_DEFAULT_COMMUNITY_LEN
31         SNMP_DEFAULT_ENTERPRISE_LENGTH
32         SNMP_DEFAULT_ERRINDEX
33         SNMP_DEFAULT_ERRSTAT
34         SNMP_DEFAULT_PEERNAME
35         SNMP_DEFAULT_REMPORT
36         SNMP_DEFAULT_REQID
37         SNMP_DEFAULT_RETRIES
38         SNMP_DEFAULT_TIME
39         SNMP_DEFAULT_TIMEOUT
40         SNMP_DEFAULT_VERSION
41         TIMED_OUT
42         snmp_get
43         snmp_getnext
44         snmp_set
45         snmp_trap
46 );
47
48 sub AUTOLOAD {
49     # This AUTOLOAD is used to 'autoload' constants from the constant()
50     # XS function.  If a constant is not found then control is passed
51     # to the AUTOLOAD in AutoLoader.
52     my($val,$pack,$file,$line);
53     local($constname);
54     ($constname = $AUTOLOAD) =~ s/.*:://;
55     # croak "&$module::constant not defined" if $constname eq 'constant';
56     $val = constant($constname, @_ ? $_[0] : 0);
57     if ($! != 0) {
58         if ($! =~ /Invalid/) {
59             $AutoLoader::AUTOLOAD = $AUTOLOAD;
60             goto &AutoLoader::AUTOLOAD;
61         }
62         else {
63             ($pack,$file,$line) = caller;
64             die "Your vendor has not defined SNMP macro $constname, used at $file line $line.
65 ";
66         }
67     }
68     eval "sub $AUTOLOAD { $val }";
69     goto &$AUTOLOAD;
70 }
71
72 bootstrap SNMP;
73
74 # Preloaded methods go here.
75
76 # Package variables
77 tie $SNMP::debugging, SNMP::DEBUGGING;
78 tie $SNMP::debug_internals, SNMP::DEBUG_INTERNALS;
79 tie $SNMP::dump_packet, SNMP::DUMP_PACKET;
80 tie %SNMP::MIB, SNMP::MIB;
81 tie $SNMP::save_descriptions, SNMP::MIB::SAVE_DESCR;
82 tie $SNMP::replace_newer, SNMP::MIB::REPLACE_NEWER;
83
84 %SNMP::V3_SEC_LEVEL_MAP = (noAuthNoPriv => 1, authNoPriv => 2, authPriv =>3);
85
86 $auto_init_mib = 1; # enable automatic MIB loading at session creation time
87 $use_long_names = 0; # non-zero to prefer longer mib textual identifiers rather
88                    # than just leaf indentifiers (see translateObj)
89                    # may also be set on a per session basis(see UseLongNames)
90 $use_sprint_value = 0; # non-zero to enable formatting of response values
91                    # using the snmp libraries "snprint_value"
92                    # may also be set on a per session basis(see UseSprintValue)
93                    # note: returned values not suitable for 'set' operations
94 $use_enums = 0; # non-zero to return integers as enums and allow sets
95                 # using enums where appropriate - integer data will
96                 # still be accepted for set operations
97                 # may also be set on a per session basis (see UseEnums)
98 $use_numeric = 0; # non-zero to return object tags as numeric OID's instead
99                   # of converting to textual representations.  use_long_names,
100                   # if non-zero, returns the entire OID, otherwise, return just
101                   # the label portion.  use_long_names is also set if the
102                   # use_numeric variable is set.
103 %MIB = ();      # tied hash to access libraries internal mib tree structure
104                 # parsed in from mib files
105 $verbose = 0;   # controls warning/info output of SNMP module,
106                 # 0 => no output, 1 => enables warning and info
107                 # output from SNMP module itself (is also controlled
108                 # by SNMP::debugging)
109 $debugging = 0; # non-zero to globally enable libsnmp do_debugging output
110                 # set to >= 2 to enabling packet dumping (see below)
111 $dump_packet = 0; # non-zero to globally enable libsnmp dump_packet output.
112                   # is also enabled when $debugging >= 2
113 $save_descriptions = 0; #tied scalar to control saving descriptions during
114                # mib parsing - must be set prior to mib loading
115 $best_guess = 0;  # determine whether or not to enable best-guess regular
116                   # expression object name translation
117 $replace_newer = 0; # determine whether or not to tell the parser to replace
118                     # older MIB modules with newer ones when loading MIBs.
119                     # WARNING: This can cause an incorrect hierarchy.
120
121 sub setMib {
122 # loads mib from file name provided
123 # setting second arg to true causes currently loaded mib to be replaced
124 # otherwise mib file will be added to existing loaded mib database
125 # NOTE: now deprecated in favor of addMibFiles and new module based funcs
126    my $file = shift;
127    my $force = shift || '0';
128    return 0 if $file and not (-r $file);
129    SNMP::_read_mib($file,$force);
130 }
131
132 sub initMib {
133 # eqivalent to calling the snmp library init_mib if Mib is NULL
134 # if Mib is already loaded this function does nothing
135 # Pass a zero valued argument to get minimal mib tree initialzation
136 # If non zero agrgument or no argument then full mib initialization
137
138   SNMP::init_snmp("perl");
139   return;
140
141
142   if (defined $_[0] and $_[0] == 0) {
143     SNMP::_init_mib_internals();
144   } else {
145     SNMP::_read_mib("");
146   }
147 }
148
149 sub addMibDirs {
150 # adds directories to search path when a module is requested to be loaded
151   SNMP::init_snmp("perl");
152   foreach (@_) {
153     SNMP::_add_mib_dir($_) or return undef;
154   }
155   return 1;
156 }
157
158 sub addMibFiles {
159 # adds mib definitions to currently loaded mib database from
160 # file(s) supplied
161   SNMP::init_snmp("perl");
162   foreach (@_) {
163     SNMP::_read_mib($_) or return undef;
164   }
165   return 1;
166 }
167
168 sub loadModules {
169 # adds mib module definitions to currently loaded mib database.
170 # Modules will be searched from previously defined mib search dirs
171 # Passing and arg of 'ALL' will cause all known modules to be loaded
172    SNMP::init_snmp("perl");
173    foreach (@_) {
174      SNMP::_read_module($_) or return undef;
175    }
176    return 1;
177 }
178
179 sub unloadModules {
180 # causes modules to be unloaded from mib database
181 # Passing and arg of 'ALL' will cause all known modules to be unloaded
182   warn("SNMP::unloadModules not implemented! (yet)");
183 }
184
185 sub translateObj {
186 # translate object identifier(tag or numeric) into alternate representation
187 # (i.e., sysDescr => '.1.3.6.1.2.1.1.1' and '.1.3.6.1.2.1.1.1' => sysDescr)
188 # when $SNMP::use_long_names or second arg is non-zero the translation will
189 # return longer textual identifiers (e.g., system.sysDescr)
190 # if Mib is not loaded and $SNMP::auto_init_mib is enabled Mib will be loaded
191 # returns 'undef' upon failure
192    SNMP::init_snmp("perl");
193    my $obj = shift;
194    my $long_names = shift || $SNMP::use_long_names;
195    return undef if not defined $obj;
196    my $res;
197    if ($obj =~ /^\.?(\d+\.)*\d+$/) {
198       $res = SNMP::_translate_obj($obj,1,$long_names,$SNMP::auto_init_mib,0);
199    } elsif ($obj =~ /(\.\d+)*$/ && $SNMP::best_guess == 0) {
200       $res = SNMP::_translate_obj($`,0,$long_names,$SNMP::auto_init_mib,0);
201       $res .= $& if defined $res and defined $&;
202    } elsif ($SNMP::best_guess) {
203       $res = SNMP::_translate_obj($obj,0,$long_names,$SNMP::auto_init_mib,$SNMP::best_guess);
204    }
205
206    return($res);
207 }
208
209 sub getType {
210 # return SNMP data type for given textual identifier
211 # OBJECTID, OCTETSTR, INTEGER, NETADDR, IPADDR, COUNTER
212 # GAUGE, TIMETICKS, OPAQUE, or undef
213   my $tag = shift;
214   SNMP::_get_type($tag);
215 }
216
217 sub mapEnum {
218 # return the corresponding integer value *or* tag for a given MIB attribute
219 # and value. The function will sense which direction to perform the conversion
220 # various arg formats are supported
221 #    $val = SNMP::mapEnum($varbind); # note: will update $varbind
222 #    $val = SNMP::mapEnum('ipForwarding', 'forwarding');
223 #    $val = SNMP::mapEnum('ipForwarding', 1);
224 #
225   my $var = shift;
226   my ($tag, $val, $update);
227   if (ref($var) =~ /ARRAY/ or ref($var) =~ /Varbind/) {
228       $tag = $var->[$SNMP::Varbind::tag_f];
229       $val = $var->[$SNMP::Varbind::val_f];
230       $update = 1;
231   } else {
232       $tag = $var;
233       $val = shift;
234   }
235   my $iflag = $val =~ /^\d+$/;
236   my $res = SNMP::_map_enum($tag, $val, $iflag);
237   if ($update and defined $res) { $var->[$SNMP::Varbind::val_f] = $res; }
238   return($res);
239 }
240
241 %session_params = (DestHost => 1,
242                    Community => 1,
243                    Version => 1,
244                    Timeout => 1,
245                    Retries => 1,
246                    RemotePort => 1,
247                    LocalPort => 1);
248
249 sub strip_session_params {
250     my @params;
251     my @args;
252     my $param;
253     while ($param = shift) {
254         push(@params,$param, shift), next
255             if $session_params{$param};
256         push(@args,$param);
257     }
258     @_ = @args;
259     @params;
260 }
261
262
263 sub snmp_get {
264 # procedural form of 'get' method. sometimes quicker to code
265 # but is less efficient since the Session is created and destroyed
266 # with each call. Takes all the parameters of both SNMP::Session::new and
267 # SNMP::Session::get (*NOTE*: this api does not support async callbacks)
268
269     my @sess_params = &strip_session_params;
270     my $sess = new SNMP::Session(@sess_params);
271
272     $sess->get(@_);
273 }
274
275 sub snmp_getnext {
276 # procedural form of 'getnext' method. sometimes quicker to code
277 # but is less efficient since the Session is created and destroyed
278 # with each call. Takes all the parameters of both SNMP::Session::new and
279 # SNMP::Session::getnext (*NOTE*: this api does not support async callbacks)
280
281     my @sess_params = &strip_session_params;
282     my $sess = new SNMP::Session(@sess_params);
283
284     $sess->getnext(@_);
285 }
286
287 sub snmp_set {
288 # procedural form of 'set' method. sometimes quicker to code
289 # but is less efficient since the Session is created and destroyed
290 # with each call. Takes all the parameters of both SNMP::Session::new and
291 # SNMP::Session::set (*NOTE*: this api does not support async callbacks)
292
293     my @sess_params = &strip_session_params;
294     my $sess = new SNMP::Session(@sess_params);
295
296     $sess->set(@_);
297 }
298
299 sub snmp_trap {
300 # procedural form of 'trap' method. sometimes quicker to code
301 # but is less efficient since the Session is created and destroyed
302 # with each call. Takes all the parameters of both SNMP::TrapSession::new and
303 # SNMP::TrapSession::trap
304
305     my @sess_params = &strip_session_params;
306     my $sess = new SNMP::TrapSession(@sess_params);
307
308     $sess->trap(@_);
309 }
310
311 sub MainLoop {
312     my $time = shift;
313     my $callback = shift;
314     my $time_sec = ($time ? int $time : 0);
315     my $time_usec = ($time ? int(($time-$time_sec)*1000000) : 0);
316     SNMP::_main_loop($time_sec,$time_usec,$callback);
317 }
318
319 sub finish {
320     SNMP::_mainloop_finish();
321 }
322
323 sub reply_cb {
324     # callback function for async snmp calls
325     # when triggered, will do a SNMP read on the
326     # given fd
327     my $fd = shift;
328   SNMP::_read_on_fd($fd);
329 }
330
331 sub select_info {
332     # retrieves SNMP used fd's and timeout info
333     # calculates timeout in fractional seconds
334     # ( easy to use with select statement )
335     my($block, $to_sec, $to_usec, @fd_set)=SNMP::_get_select_info();
336     my $time_sec_dec = ($block? 0 : $to_sec + $to_usec * 1e-6);
337     #print "fd's for snmp -> ", @fd_set, "\n";
338     #print "block               -> ", $block, "\n";
339     #print "timeout_sec -> ", $to_sec, "\n";
340     #print "timeout_usec        -> ", $to_usec, "\n";
341     #print "timeout dec -> ", $time_sec_dec, "\n";
342     return ($time_sec_dec,@fd_set);
343 }
344
345 sub check_timeout {
346   # check to see if a snmp session
347   # timed out, and if so triggers
348   # the callback function
349   SNMP::_check_timeout();
350   # check to see when have to check again
351   my($block, $to_sec, $to_usec, @fd_set)=SNMP::_get_select_info();
352   my $time_sec_dec = ($block? 0 : $to_sec + $to_usec * 1e-6);
353   #print "fd's for snmp -> ", @fd_set, "\n";
354   #print "block         -> ", $block, "\n";
355   #print "timeout_sec   -> ", $to_sec, "\n";
356   #print "timeout_usec  -> ", $to_usec, "\n";
357   #print "timeout dec   -> ", $time_sec_dec, "\n";
358   return ($time_sec_dec);
359 }
360
361 sub _tie {
362 # this is a little implementation hack so ActiveState can access pp_tie
363 # thru perl code. All other environments allow the calling of pp_tie from
364 # XS code but AS was not exporting it when PERL_OBJECT was used.
365 #
366 # short term solution was call this perl func which calls 'tie'
367 #
368 # longterm fix is to supply a patch which allows AS to export pp_tie in
369 # such a way that it can be called from XS code. gsarathy says:
370 # a patch to util.c is needed to provide access to PL_paddr
371 # so it is possible to call PL_paddr[OP_TIE] as the compiler does
372     tie($_[0],$_[1],$_[2],$_[3]);
373 }
374
375 package SNMP::Session;
376
377 sub new {
378    my $type = shift;
379    my $this = {};
380    my ($name, $aliases, $host_type, $len, $thisaddr);
381
382    SNMP::init_snmp("perl");
383
384    %$this = @_;
385
386    $this->{ErrorStr} = ''; # if methods return undef check for expln.
387    $this->{ErrorNum} = 0;  # contains SNMP error return
388
389    $this->{Version} ||= 
390      NetSNMP::default_store::netsnmp_ds_get_int(NetSNMP::default_store::NETSNMP_DS_LIBRARY_ID, 
391                                       NetSNMP::default_store::NETSNMP_DS_LIB_SNMPVERSION) ||
392                                         SNMP::SNMP_DEFAULT_VERSION();
393
394    if ($this->{Version} eq 128) {
395        # special handling of the bogus v1 definition.
396        $this->{Version} = 1;
397    }
398
399    # allow override of local SNMP port
400    $this->{LocalPort} ||= 0;
401
402    # destination host defaults to localhost
403    $this->{DestHost} ||= 'localhost';
404
405    # community defaults to public
406    $this->{Community} ||= NetSNMP::default_store::netsnmp_ds_get_string(NetSNMP::default_store::NETSNMP_DS_LIBRARY_ID(), 
407                                         NetSNMP::default_store::NETSNMP_DS_LIB_COMMUNITY()) || 'public';
408
409    # number of retries before giving up, defaults to SNMP_DEFAULT_RETRIES
410    $this->{Retries} = SNMP::SNMP_DEFAULT_RETRIES() unless defined($this->{Retries});
411
412    # timeout before retry, defaults to SNMP_DEFAULT_TIMEOUT
413    $this->{Timeout} = SNMP::SNMP_DEFAULT_TIMEOUT() unless defined($this->{Timeout});
414    # flag to enable fixing pdu and retrying with a NoSuch error
415    $this->{RetryNoSuch} ||= 0;
416
417    # backwards compatibility.  Make host = host:port
418    if ($this->{RemotePort} && $this->{DestHost} !~ /:/) {
419        $this->{DestHost} = $this->{DestHost} . ":" . $this->{RemotePort};
420    }
421
422    if ($this->{Version} eq '1' or $this->{Version} eq '2'
423        or $this->{Version} eq '2c') {
424        $this->{SessPtr} = SNMP::_new_session($this->{Version},
425                                              $this->{Community},
426                                              $this->{DestHost},
427                                              $this->{LocalPort},
428                                              $this->{Retries},
429                                              $this->{Timeout},
430                                              );
431    } elsif ($this->{Version} eq '3' ) {
432        $this->{SecName} ||= 
433            NetSNMP::default_store::netsnmp_ds_get_string(NetSNMP::default_store::NETSNMP_DS_LIBRARY_ID(), 
434                          NetSNMP::default_store::NETSNMP_DS_LIB_SECNAME()) || 
435                            'initial';
436        if (!$this->{SecLevel}) {
437            $this->{SecLevel} = 
438                NetSNMP::default_store::netsnmp_ds_get_int(NetSNMP::default_store::NETSNMP_DS_LIBRARY_ID(), 
439                           NetSNMP::default_store::NETSNMP_DS_LIB_SECLEVEL()) || 
440                               $SNMP::V3_SEC_LEVEL_MAP{'noAuthNoPriv'};
441        } elsif ($this->{SecLevel} !~ /^\d+$/) {
442            $this->{SecLevel} = $SNMP::V3_SEC_LEVEL_MAP{$this->{SecLevel}};
443        }
444        $this->{SecEngineId} ||= '';
445        $this->{ContextEngineId} ||= $this->{SecEngineId};
446        $this->{Context} ||= 
447            NetSNMP::default_store::netsnmp_ds_get_string(NetSNMP::default_store::NETSNMP_DS_LIBRARY_ID(), 
448                          NetSNMP::default_store::NETSNMP_DS_LIB_CONTEXT()) || '';
449        $this->{AuthProto} ||= 'MD5'; # defaults XXX
450        $this->{AuthPass} ||=
451        NetSNMP::default_store::netsnmp_ds_get_string(NetSNMP::default_store::NETSNMP_DS_LIBRARY_ID(), 
452                      NetSNMP::default_store::NETSNMP_DS_LIB_AUTHPASSPHRASE()) ||
453        NetSNMP::default_store::netsnmp_ds_get_string(NetSNMP::default_store::NETSNMP_DS_LIBRARY_ID(), 
454                      NetSNMP::default_store::NETSNMP_DS_LIB_PASSPHRASE()) || '';
455        $this->{PrivProto} ||= 'DES';  # defaults XXX
456        $this->{PrivPass} ||=
457        NetSNMP::default_store::netsnmp_ds_get_string(NetSNMP::default_store::NETSNMP_DS_LIBRARY_ID(), 
458                      NetSNMP::default_store::NETSNMP_DS_LIB_PRIVPASSPHRASE()) ||
459        NetSNMP::default_store::netsnmp_ds_get_string(NetSNMP::default_store::NETSNMP_DS_LIBRARY_ID(), 
460                      NetSNMP::default_store::NETSNMP_DS_LIB_PASSPHRASE()) || '';
461        $this->{EngineBoots} = 0 if not defined $this->{EngineBoots};
462        $this->{EngineTime} = 0 if not defined $this->{EngineTime};
463
464        $this->{SessPtr} = SNMP::_new_v3_session($this->{Version},
465                                                 $this->{DestHost},
466                                                 $this->{Retries},
467                                                 $this->{Timeout},
468                                                 $this->{SecName},
469                                                 $this->{SecLevel},
470                                                 $this->{SecEngineId},
471                                                 $this->{ContextEngineId},
472                                                 $this->{Context},
473                                                 $this->{AuthProto},
474                                                 $this->{AuthPass},
475                                                 $this->{PrivProto},
476                                                 $this->{PrivPass},
477                                                 $this->{EngineBoots},
478                                                 $this->{EngineTime},
479                                                 );
480    }
481    unless ($this->{SessPtr}) {
482        warn("unable to create session") if $SNMP::verbose;
483        return undef;
484    }
485
486    SNMP::initMib($SNMP::auto_init_mib); # ensures that *some* mib is loaded
487
488    $this->{UseLongNames} ||= $SNMP::use_long_names;
489    $this->{UseSprintValue} ||= $SNMP::use_sprint_value;
490    $this->{UseEnums} ||= $SNMP::use_enums;
491    $this->{UseNumeric} ||= $SNMP::use_numeric;
492
493    # Force UseLongNames if UseNumeric is in use.
494    $this->{UseLongNames}++  if $this->{UseNumeric};
495
496    bless $this, $type;
497 }
498
499 sub update {
500 # *Not Implemented*
501 # designed to update the fields of session to allow retargetting to different
502 # host, community name change, timeout, retry changes etc. Unfortunately not
503 # working yet because some updates (the address in particular) need to be
504 # done on the internal session pointer which cannot be fetched w/o touching
505 # globals at this point which breaks win32. A patch to the ucd-snmp toolkit
506 # is needed
507    my $this = shift;
508    my ($name, $aliases, $host_type, $len, $thisaddr);
509    my %new_fields = @_;
510
511    @$this{keys %new_fields} = values %new_fields;
512
513    $this->{UseLongNames} ||= $SNMP::use_long_names;
514    $this->{UseSprintValue} ||= $SNMP::use_sprint_value;
515    $this->{UseEnums} ||= $SNMP::use_enums;
516    $this->{UseNumeric} ||= $SNMP::use_numeric;
517
518    # Force UseLongNames if UseNumeric is in use.
519    $this->{UseLongNames}++  if $this->{UseNumeric};
520
521    SNMP::_update_session($this->{Version},
522                  $this->{Community},
523                  $this->{DestHost},
524                  $this->{RemotePort},
525                  $this->{LocalPort},
526                  $this->{Retries},
527                  $this->{Timeout},
528                 );
529
530
531 }
532
533 sub set {
534    my $this = shift;
535    my $vars = shift;
536    my $varbind_list_ref;
537    my $res = 0;
538
539    if (ref($vars) =~ /SNMP::VarList/) {
540      $varbind_list_ref = $vars;
541    } elsif (ref($vars) =~ /SNMP::Varbind/) {
542      $varbind_list_ref = [$vars];
543    } elsif (ref($vars) =~ /ARRAY/) {
544      $varbind_list_ref = [$vars];
545      $varbind_list_ref = $vars if ref($$vars[0]) =~ /ARRAY/;
546    } else {
547      my ($tag, $iid) = ($vars =~ /^((?:\.\d+)+|(?:\w+(?:\-*\w+)+))\.?(.*)$/);
548      my $val = shift;
549      $varbind_list_ref = [[$tag, $iid, $val]];
550    }
551    my $cb = shift;
552
553    $res = SNMP::_set($this, $varbind_list_ref, $cb);
554 }
555
556 sub get {
557    my $this = shift;
558    my $vars = shift;
559    my ($varbind_list_ref, @res);
560
561    if (ref($vars) =~ /SNMP::VarList/) {
562      $varbind_list_ref = $vars;
563    } elsif (ref($vars) =~ /SNMP::Varbind/) {
564      $varbind_list_ref = [$vars];
565    } elsif (ref($vars) =~ /ARRAY/) {
566      $varbind_list_ref = [$vars];
567      $varbind_list_ref = $vars if ref($$vars[0]) =~ /ARRAY/;
568    } else {
569      my ($tag, $iid) = ($vars =~ /^((?:\.\d+)+|(?:\w+(?:\-*\w+)+))\.?(.*)$/);
570      $varbind_list_ref = [[$tag, $iid]];
571    }
572
573    my $cb = shift;
574
575    @res = SNMP::_get($this, $this->{RetryNoSuch}, $varbind_list_ref, $cb);
576
577    return(wantarray() ? @res : $res[0]);
578 }
579
580 sub fget {
581    my $this = shift;
582    my $vars = shift;
583    my ($varbind_list_ref, @res);
584
585    if (ref($vars) =~ /SNMP::VarList/) {
586      $varbind_list_ref = $vars;
587    } elsif (ref($vars) =~ /SNMP::Varbind/) {
588      $varbind_list_ref = [$vars];
589    } elsif (ref($vars) =~ /ARRAY/) {
590      $varbind_list_ref = [$vars];
591      $varbind_list_ref = $vars if ref($$vars[0]) =~ /ARRAY/;
592    } else {
593      my ($tag, $iid) = ($vars =~ /^((?:\.\d+)+|(?:\w+(?:\-*\w+)+))\.?(.*)$/);
594      $varbind_list_ref = [[$tag, $iid]];
595    }
596
597    my $cb = shift;
598
599    SNMP::_get($this, $this->{RetryNoSuch}, $varbind_list_ref, $cb);
600
601    foreach $varbind (@$varbind_list_ref) {
602      $sub = $this->{VarFormats}{$varbind->[$SNMP::Varbind::tag_f]} ||
603          $this->{TypeFormats}{$varbind->[$SNMP::Varbind::type_f]};
604      &$sub($varbind) if defined $sub;
605      push(@res, $varbind->[$SNMP::Varbind::val_f]);
606    }
607
608    return(wantarray() ? @res : $res[0]);
609 }
610
611 sub getnext {
612    my $this = shift;
613    my $vars = shift;
614    my ($varbind_list_ref, @res);
615
616    if (ref($vars) =~ /SNMP::VarList/) {
617      $varbind_list_ref = $vars;
618    } elsif (ref($vars) =~ /SNMP::Varbind/) {
619      $varbind_list_ref = [$vars];
620    } elsif (ref($vars) =~ /ARRAY/) {
621      $varbind_list_ref = [$vars];
622      $varbind_list_ref = $vars if ref($$vars[0]) =~ /ARRAY/;
623    } else {
624      my ($tag, $iid) = ($vars =~ /^((?:\.\d+)+|(?:\w+(?:\-*\w+)+))\.?(.*)$/);
625      $varbind_list_ref = [[$tag, $iid]];
626    }
627
628    my $cb = shift;
629
630    @res = SNMP::_getnext($this, $varbind_list_ref, $cb);
631
632    return(wantarray() ? @res : $res[0]);
633 }
634
635 sub fgetnext {
636    my $this = shift;
637    my $vars = shift;
638    my ($varbind_list_ref, @res);
639
640    if (ref($vars) =~ /SNMP::VarList/) {
641      $varbind_list_ref = $vars;
642    } elsif (ref($vars) =~ /SNMP::Varbind/) {
643      $varbind_list_ref = [$vars];
644    } elsif (ref($vars) =~ /ARRAY/) {
645      $varbind_list_ref = [$vars];
646      $varbind_list_ref = $vars if ref($$vars[0]) =~ /ARRAY/;
647    } else {
648      my ($tag, $iid) = ($vars =~ /^((?:\.\d+)+|(?:\w+(?:\-*\w+)+))\.?(.*)$/);
649      $varbind_list_ref = [[$tag, $iid]];
650    }
651
652    my $cb = shift;
653
654    SNMP::_getnext($this, $varbind_list_ref, $cb);
655
656    foreach $varbind (@$varbind_list_ref) {
657      $sub = $this->{VarFormats}{$varbind->[$SNMP::Varbind::tag_f]} ||
658          $this->{TypeFormats}{$varbind->[$SNMP::Varbind::type_f]};
659      &$sub($varbind) if defined $sub;
660      push(@res, $varbind->[$SNMP::Varbind::val_f]);
661    }
662
663    return(wantarray() ? @res : $res[0]);
664 }
665
666 sub getbulk {
667    my $this = shift;
668    my $nonrepeaters = shift;
669    my $maxrepetitions = shift;
670    my $vars = shift;
671    my ($varbind_list_ref, @res);
672
673    if (ref($vars) =~ /SNMP::VarList/) {
674      $varbind_list_ref = $vars;
675    } elsif (ref($vars) =~ /SNMP::Varbind/) {
676      $varbind_list_ref = [$vars];
677    } elsif (ref($vars) =~ /ARRAY/) {
678      $varbind_list_ref = [$vars];
679      $varbind_list_ref = $vars if ref($$vars[0]) =~ /ARRAY/;
680    } else {
681      my ($tag, $iid) = ($vars =~ /^((?:\.\d+)+|(?:\w+(?:\-*\w+)+))\.?(.*)$/);
682      $varbind_list_ref = [[$tag, $iid]];
683    }
684
685    my $cb = shift;
686
687    @res = SNMP::_getbulk($this, $nonrepeaters, $maxrepetitions, $varbind_list_ref, $cb);
688
689    return(wantarray() ? @res : $res[0]);
690 }
691
692 sub bulkwalk {
693    my $this = shift;
694    my $nonrepeaters = shift;
695    my $maxrepetitions = shift;
696    my $vars = shift;
697    my ($varbind_list_ref, @res);
698
699    if (ref($vars) =~ /SNMP::VarList/) {
700       $varbind_list_ref = $vars;
701    } elsif (ref($vars) =~ /SNMP::Varbind/) {
702       $varbind_list_ref = [$vars];
703    } elsif (ref($vars) =~ /ARRAY/) {
704       $varbind_list_ref = [$vars];
705       $varbind_list_ref = $vars if ref($$vars[0]) =~ /ARRAY/;
706    } else {
707       my ($tag, $iid) = ($vars =~ /^((?:\.\d+)+|\w+)\.?(.*)$/);
708       $varbind_list_ref = [[$tag, $iid]];
709    }
710
711    if (scalar @$varbind_list_ref == 0) {
712       $this->{ErrorNum} = SNMP::constant("SNMPERR_GENERR", 0);
713       $this->{ErrorStr} = "cannot bulkwalk() empty variable list";
714       return undef;
715    }
716    if (scalar @$varbind_list_ref < $nonrepeaters) {
717       $this->{ErrorNum} = SNMP::constant("SNMPERR_GENERR", 0);
718       $this->{ErrorStr} = "bulkwalk() needs at least $nonrepeaters varbinds";
719       return undef;
720    }
721
722    my $cb = shift;
723    @res = SNMP::_bulkwalk($this, $nonrepeaters, $maxrepetitions,
724                                                 $varbind_list_ref, $cb);
725
726    # Return, in list context, a copy of the array of arrays of Varbind refs.
727    # In scalar context, return either a reference to the array of arrays of
728    # Varbind refs, or the request ID for an asynchronous bulkwalk.  This is
729    # a compromise between the getbulk()-ish return, and the more useful array
730    # of arrays of Varbinds return from the synchronous bulkwalk().
731    #
732    return @res if (wantarray());
733    return defined($cb) ? $res[0] : \@res;
734 }
735
736 %trap_type = (coldStart => 0, warmStart => 1, linkDown => 2, linkUp => 3,
737               authFailure => 4, egpNeighborLoss => 5, specific => 6 );
738 sub trap {
739 # (v1) enterprise, agent, generic, specific, uptime, <vars>
740 # $sess->trap(enterprise=>'.1.3.6.1.4.1.2021', # or 'ucdavis' [default]
741 #             agent => '127.0.0.1', # or 'localhost',[default 1st intf on host]
742 #             generic => specific,  # can be omitted if 'specific' supplied
743 #             specific => 5,        # can be omitted if 'generic' supplied
744 #             uptime => 1234,       # default to localhost uptime (0 on win32)
745 #             [[ifIndex, 1, 1],[sysLocation, 0, "here"]]); # optional vars
746 #                                                          # always last
747 # (v2) oid, uptime, <vars>
748 # $sess->trap(uptime => 1234,
749 #             oid => 'snmpRisingAlarm',
750 #             [[ifIndex, 1, 1],[sysLocation, 0, "here"]]); # optional vars
751 #                                                          # always last
752 #                                                          # always last
753
754
755    my $this = shift;
756    my $vars = pop if ref($_[$#_]); # last arg may be varbind or varlist
757    my %param = @_;
758    my ($varbind_list_ref, @res);
759
760    if (ref($vars) =~ /SNMP::VarList/) {
761      $varbind_list_ref = $vars;
762    } elsif (ref($vars) =~ /SNMP::Varbind/) {
763      $varbind_list_ref = [$vars];
764    } elsif (ref($vars) =~ /ARRAY/) {
765      $varbind_list_ref = [$vars];
766      $varbind_list_ref = $vars if ref($$vars[0]) =~ /ARRAY/;
767    }
768
769    if ($this->{Version} eq '1') {
770        my $enterprise = $param{enterprise} || 'ucdavis';
771        $enterprise = SNMP::translateObj($enterprise)
772            unless $enterprise =~ /^[\.\d]+$/;
773        my $agent = $param{agent} || '';
774        my $generic = $param{generic} || 'specific';
775        $generic = $trap_type{$generic} || $generic;
776        my $uptime = $param{uptime} || SNMP::_sys_uptime();
777        my $specific = $param{specific} || 0;
778        @res = SNMP::_trapV1($this, $enterprise, $agent, $generic, $specific,
779                           $uptime, $varbind_list_ref);
780    } elsif  (($this->{Version} eq '2')|| ($this->{Version} eq '2c')) {
781        my $trap_oid = $param{oid} || $param{trapoid} || '.0.0';
782        my $uptime = $param{uptime} || SNMP::_sys_uptime();
783        @res = SNMP::_trapV2($this, $uptime, $trap_oid, $varbind_list_ref);
784    }
785
786    return(wantarray() ? @res : $res[0]);
787 }
788
789 sub inform {
790 # (v3) oid, uptime, <vars>
791 # $sess->inform(uptime => 1234,
792 #             oid => 'coldStart',
793 #             [[ifIndex, 1, 1],[sysLocation, 0, "here"]]); # optional vars
794 #                                                          # then callback
795                                                            # always last
796
797
798    my $this = shift;
799    my $vars;
800    my $cb;
801    $cb = pop if ref($_[$#_]) eq 'CODE'; # last arg may be code
802    $vars = pop if ref($_[$#_]); # varbind or varlist
803    my %param = @_;
804    my ($varbind_list_ref, @res);
805
806    if (ref($vars) =~ /SNMP::VarList/) {
807      $varbind_list_ref = $vars;
808    } elsif (ref($vars) =~ /SNMP::Varbind/) {
809      $varbind_list_ref = [$vars];
810    } elsif (ref($vars) =~ /ARRAY/) {
811      $varbind_list_ref = [$vars];
812      $varbind_list_ref = $vars if ref($$vars[0]) =~ /ARRAY/;
813    }
814
815    my $trap_oid = $param{oid} || $param{trapoid};
816    my $uptime = $param{uptime} || SNMP::_sys_uptime();
817
818    if($this->{Version} eq '3') {
819      @res = SNMP::_inform($this, $uptime, $trap_oid, $varbind_list_ref, $cb);
820    } else {
821      warn("error:inform: This version doesn't support the command\n");
822    }
823
824    return(wantarray() ? @res : $res[0]);
825 }
826
827 package SNMP::TrapSession;
828 @ISA = ('SNMP::Session');
829
830 sub new {
831    my $type = shift;
832
833    # allow override of remote SNMP trap port
834    unless (grep(/RemotePort/, @_)) {
835        push(@_, 'RemotePort', 162); # push on new default for trap session
836    }
837
838    SNMP::Session::new($type, @_);
839 }
840
841 package SNMP::Varbind;
842
843 $tag_f = 0;
844 $iid_f = 1;
845 $val_f = 2;
846 $type_f = 3;
847 $time_f = 4;
848
849 sub new {
850    my $type = shift;
851    my $this = shift;
852    $this ||= [];
853    bless $this;
854 }
855
856 sub tag {
857   $_[0]->[$tag_f];
858 }
859
860 sub iid {
861   $_[0]->[$iid_f];
862 }
863
864 sub val {
865   $_[0]->[$val_f];
866 }
867
868 sub type {
869   $_[0]->[$type_f];
870 }
871
872 sub name {
873    if (defined($_[0]->[$iid_f]) && ($_[0]->[$iid_f] =~ m/^[0-9]+$/)) {
874       return $_[0]->[$tag_f] . "." . $_[0]->[$iid_f];
875    }
876
877    return $_[0]->[$tag_f];
878 }
879
880 sub fmt {
881     my $self = shift;
882     return $self->name . " = \"" . $self->val . "\" (" . $self->type . ")";
883 }
884
885
886 #sub DESTROY {
887 #    print "SNMP::Varbind::DESTROY($_[0])\n";
888 #}
889
890 package SNMP::VarList;
891
892 sub new {
893    my $type = shift;
894    my $this = [];
895    my $varb;
896    foreach $varb (@_) {
897      $varb = new SNMP::Varbind($varb) unless ref($varb) =~ /SNMP::Varbind/;
898      push(@{$this}, $varb);
899    }
900
901    bless $this;
902 }
903
904 #sub DESTROY {
905 #    print "SNMP::VarList::DESTROY($_[0])\n";
906 #}
907
908 package SNMP::DEBUGGING;
909 # controls info/debugging output from SNMP module and libsnmp
910 # $SNMP::debugging == 1    =>   enables general info and warning output
911 #                                (eqiv. to setting $SNMP::verbose)
912 # $SNMP::debugging == 2    =>   enables do_debugging from libsnmp as well
913 # $SNMP::debugging == 3    =>   enables packet_dump from libsnmp as well
914 sub TIESCALAR { my $class = shift; my $val; bless \$val, $class; }
915
916 sub FETCH { ${$_[0]}; }
917
918 sub STORE {
919     $SNMP::verbose = $_[1];
920     SNMP::_set_debugging($_[1]>1);
921     $SNMP::dump_packet = ($_[1]>2);
922     ${$_[0]} = $_[1];
923 }
924
925 sub DELETE {
926     $SNMP::verbose = 0;
927     SNMP::_set_debugging(0);
928     $SNMP::dump_packet = 0;
929     ${$_[0]} = undef;
930 }
931
932 package SNMP::DEBUG_INTERNALS;          # Controls SNMP.xs debugging.
933 sub TIESCALAR { my $class = shift; my $val; bless \$val, $class; }
934
935 sub FETCH { ${$_[0]}; }
936
937 sub STORE {
938     SNMP::_debug_internals($_[1]);
939     ${$_[0]} = $_[1];
940 }
941
942 sub DELETE {
943     SNMP::_debug_internals(0);
944     ${$_[0]} = undef;
945 }
946
947 package SNMP::DUMP_PACKET;
948 # controls packet dump output from libsnmp
949
950 sub TIESCALAR { my $class = shift; my $val; bless \$val, $class; }
951
952 sub FETCH { ${$_[0]}; }
953
954 sub STORE { SNMP::_dump_packet($_[1]); ${$_[0]} = $_[1]; }
955
956 sub DELETE { SNMP::_dump_packet(0); ${$_[0]} = 0; }
957
958 package SNMP::MIB;
959
960 sub TIEHASH {
961     bless {};
962 }
963
964 sub FETCH {
965     my $this = shift;
966     my $key = shift;
967
968     if (!defined $this->{$key}) {
969         tie(%{$this->{$key}}, SNMP::MIB::NODE, $key) or return undef;
970     }
971     $this->{$key};
972 }
973
974 sub STORE {
975     warn "STORE(@_) : write access to the MIB not implemented\n";
976 }
977
978 sub DELETE {
979     delete $_[0]->{$_[1]}; # just delete cache entry
980 }
981
982 sub FIRSTKEY { return '.1'; } # this should actually start at .0 but
983                               # because nodes are not stored in lexico
984                               # order in ucd-snmp node tree walk will
985                               # miss most of the tree
986 sub NEXTKEY { # this could be sped up by using an XS __get_next_oid maybe
987    my $node = $_[0]->FETCH($_[1])->{nextNode};
988    $node->{objectID};
989 }
990 sub EXISTS { exists $_[0]->{$_[1]} || $_[0]->FETCH($_[1]); }
991 sub CLEAR { undef %{$_[0]}; } # clear the cache
992
993 package SNMP::MIB::NODE;
994 my %node_elements =
995     (
996      objectID => 0, # dotted decimal fully qualified OID
997      label => 0,    # leaf textual identifier (e.g., 'sysDescr')
998      subID => 0,    # leaf numeric OID component of objectID (e.g., '1')
999      moduleID => 0, # textual identifier for module (e.g., 'RFC1213-MIB')
1000      parent => 0,   # parent node
1001      children => 0, # array reference of children nodes
1002      indexes => 0,  # returns array of column labels
1003      varbinds => 0, # returns array of trap/notification varbinds
1004      nextNode => 0, # next lexico node (BUG! does not return in lexico order)
1005      type => 0,     # returns simple type (see getType for values)
1006      access => 0,   # returns ACCESS (ReadOnly, ReadWrite, WriteOnly,
1007                     # NoAccess, Notify, Create)
1008      status => 0,   # returns STATUS (Mandatory, Optional, Obsolete,
1009                     # Deprecated)
1010      syntax => 0,   # returns 'textualConvention' if defined else 'type'
1011      textualConvention => 0, # returns TEXTUAL-CONVENTION
1012      units => 0,    # returns UNITS
1013      hint => 0,     # returns HINT
1014      enums => 0,    # returns hash ref {tag => num, ...}
1015      ranges => 0,   # returns array ref of hash ref [{low => num, high => num}]
1016      defaultValue => 0, # returns default value
1017      description => 0, # returns DESCRIPTION ($SNMP::save_descriptions must
1018                     # be set prior to MIB initialization/parsing
1019     );
1020
1021 # sub TIEHASH - implemented in SNMP.xs
1022
1023 # sub FETCH - implemented in SNMP.xs
1024
1025 sub STORE {
1026     warn "STORE(@_): write access to MIB node not implemented\n";
1027 }
1028
1029 sub DELETE {
1030     warn "DELETE(@_): write access to MIB node not implemented\n";
1031 }
1032
1033 sub FIRSTKEY { my $k = keys %node_elements; (each(%node_elements))[0]; }
1034 sub NEXTKEY { (each(%node_elements))[0]; }
1035 sub EXISTS { exists($node_elements{$_[1]}); }
1036 sub CLEAR {
1037     warn "CLEAR(@_): write access to MIB node not implemented\n";
1038 }
1039
1040 #sub DESTROY {
1041 #    warn "DESTROY(@_): write access to MIB node not implemented\n";
1042 #    # print "SNMP::MIB::NODE::DESTROY : $_[0]->{label} ($_[0])\n";
1043 #}
1044 package SNMP::MIB::SAVE_DESCR;
1045
1046 sub TIESCALAR { my $class = shift; my $val; bless \$val, $class; }
1047
1048 sub FETCH { ${$_[0]}; }
1049
1050 sub STORE { SNMP::_set_save_descriptions($_[1]); ${$_[0]} = $_[1]; }
1051
1052 sub DELETE { SNMP::_set_save_descriptions(0); ${$_[0]} = 0; }
1053
1054 package SNMP::MIB::REPLACE_NEWER;               # Controls MIB parsing
1055
1056 sub TIESCALAR { my $class = shift; my $val; bless \$val, $class; }
1057
1058 sub FETCH { ${$_[0]}; }
1059
1060 sub STORE {
1061     SNMP::_set_replace_newer($_[1]);
1062     ${$_[0]} = $_[1];
1063 }
1064
1065 sub DELETE {
1066     SNMP::_set_replace_newer(0);
1067     ${$_[0]} = 0;
1068 }
1069
1070 package SNMP;
1071 END{SNMP::_sock_cleanup() if defined &SNMP::_sock_cleanup;}
1072 # Autoload methods go after __END__, and are processed by the autosplit prog.
1073
1074 1;
1075 __END__
1076
1077 =head1 NAME
1078
1079 SNMP - The Perl5 'SNMP' Extension Module v3.1.0 for the UCD SNMPv3 Library
1080
1081 =head1 SYNOPSIS
1082
1083  use SNMP;
1084  ...
1085  $sess = new SNMP::Session(DestHost => localhost, Community => public);
1086  $val = $sess->get('sysDescr.0');
1087  ...
1088  $vars = new SNMP::VarList([sysDescr,0], [sysContact,0], [sysLocation,0]);
1089  @vals = $sess->get($vars);
1090  ...
1091  $vb = new SNMP::Varbind();
1092  do {
1093     $val = $sess->getnext($vb);
1094     print "@{$vb}\n";
1095  } until ($sess->{ErrorNum});
1096  ...
1097  $SNMP::save_descriptions = 1;
1098  SNMP::initMib(); # assuming mib is not already loaded
1099  print "$SNMP::MIB{sysDescr}{description}\n";
1100
1101 =head1 DESCRIPTION
1102
1103
1104 Note: The perl SNMP 5.0 module which comes with net-snmp 5.0 and
1105 higher is different than previous versions in a number of ways.  Most
1106 importantly, it behaves like a proper net-snmp application and calls
1107 init_snmp properly, which means it will read configuration files and
1108 use those defaults where appropriate automatically parse MIB files,
1109 etc.  This will likely affect your perl applications if you have, for
1110 instance, default values set up in your snmp.conf file (as the perl
1111 module will now make use of those defaults).  The docmuentation,
1112 however, has sadly not been updated yet (aside from this note), nor is
1113 the read_config default usage implementation fully complete.
1114
1115 The basic operations of the SNMP protocol are provided by this module
1116 through an object oriented interface for modularity and ease of use.
1117 The primary class is SNMP::Session which encapsulates the persistent
1118 aspects of a connection between the management application and the
1119 managed agent. Internally the class is implemented as a blessed hash
1120 reference. This class supplies 'get', 'getnext', 'set', 'fget', and
1121 'fgetnext' method calls. The methods take a variety of input argument
1122 formats and support both syncronous and asyncronous operation through
1123 a polymorphic API (i.e., method behaviour varies dependent on args
1124 passed - see below).
1125
1126 =head1 SNMP::Session
1127
1128 $sess = new SNMP::Session(DestHost => 'host', ...)
1129
1130 The following arguments may be passed to new as a hash.
1131
1132 =over 4
1133
1134 =item DestHost
1135
1136 default 'localhost', hostname or ip addr of SNMP agent
1137
1138 =item Community
1139
1140 default 'public', SNMP community string (used for both R/W)
1141
1142 =item Version
1143
1144 default '1', [2 (same as 2c), 2c, 3]
1145
1146 =item RemotePort
1147
1148 default '161', allow remote UDP port to be overriden
1149
1150 =item Timeout
1151
1152 default '1000000', micro-seconds before retry
1153
1154 =item Retries
1155
1156 default '5', retries before failure
1157
1158 =item RetryNoSuch
1159
1160 default '0', if enabled NOSUCH errors in 'get' pdus will
1161 be repaired, removing the varbind in error, and resent -
1162 undef will be returned for all NOSUCH varbinds, when set
1163 to '0' this feature is disabled and the entire get request
1164 will fail on any NOSUCH error (applies to v1 only)
1165
1166 =item SecName
1167
1168 default 'initial', security name (v3)
1169
1170 =item SecLevel
1171
1172 default 'noAuthNoPriv', security level [noAuthNoPriv,
1173 authNoPriv, authPriv] (v3)
1174
1175 =item SecEngineId
1176
1177 default <none>, security engineID, will be probed if not
1178 supplied (v3)
1179
1180 =item ContextEngineId
1181
1182 default <SecEngineId>, context engineID, will be
1183 probed if not supplied (v3)
1184
1185 =item Context
1186
1187 default '', context name (v3)
1188
1189 =item AuthProto
1190
1191 default 'MD5', authentication protocol [MD5, SHA] (v3)
1192
1193 =item AuthPass
1194
1195 default <none>, authentication passphrase
1196
1197 =item PrivProto
1198
1199 default 'DES', privacy protocol [DES] (v3)
1200
1201 =item PrivPass
1202
1203 default <none>, privacy passphrase (v3)
1204
1205 =item VarFormats
1206
1207 default 'undef', used by 'fget[next]', holds an hash
1208 reference of output value formatters, (e.g., {<obj> =>
1209 <sub-ref>, ... }, <obj> must match the <obj> and format
1210 used in the get operation. A special <obj>, '*', may be
1211 used to apply all <obj>s, the supplied sub is called to
1212 translate the value to a new format. The sub is called
1213 passing the Varbind as the arg
1214
1215 =item TypeFormats
1216
1217 default 'undef', used by 'fget[next]', holds an hash
1218 reference of output value formatters, (e.g., {<type> =>
1219 <sub-ref>, ... }, the supplied sub is called to translate
1220 the value to a new format, unless a VarFormat mathces first
1221 (e.g., $sess->{TypeFormats}{INTEGER} = \&mapEnum();
1222 although this can be done more efficiently by enabling
1223 $SNMP::use_enums or session creation param 'UseEnums')
1224
1225 =item UseLongNames
1226
1227 defaults to the value of SNMP::use_long_names at time
1228 of session creation. set to non-zero to have <tags>
1229 for 'getnext' methods generated preferring longer Mib name
1230 convention (e.g., system.sysDescr vs just sysDescr)
1231
1232 =item UseSprintValue
1233
1234 defaults to the value of SNMP::use_sprint_value at time
1235 of session creation. set to non-zero to have return values
1236 for 'get' and 'getnext' methods formatted with the libraries
1237 snprint_value function. This will result in certain data types
1238 being returned in non-canonical format Note: values returned
1239 with this option set may not be appropriate for 'set' operations
1240 (see discussion of value formats in <vars> description section)
1241
1242 =item UseEnums
1243
1244 defaults to the value of SNMP::use_enums at time of session
1245 creation. set to non-zero to have integer return values
1246 converted to enumeration identifiers if possible, these values
1247 will also be acceptable when supplied to 'set' operations
1248
1249 =item UseNumeric
1250
1251 defaults to the value of SNMP::use_numeric at time of session
1252 creation. set to non-zero to have <tags> for get methods returned
1253 as numeric OID's rather than descriptions.  UseLongNames will be
1254 set so that the full OID is returned to the caller.
1255
1256 =item ErrorStr
1257
1258 read-only, holds the error message assoc. w/ last request
1259
1260 =item ErrorNum
1261
1262 read-only, holds the snmp_err or staus of last request
1263
1264 =item ErrorInd
1265
1266 read-only, holds the snmp_err_index when appropriate
1267
1268 =back
1269
1270 Private variables:
1271
1272 =over
1273
1274 =item DestAddr
1275
1276 internal field used to hold the translated DestHost field
1277
1278 =item SessPtr
1279
1280 internal field used to cache a created session structure
1281
1282 =back
1283
1284 =head2 SNMP::Session methods
1285
1286 =over
1287
1288 =item $sess->update(E<lt>fieldsE<gt>)
1289
1290 Updates the SNMP::Session object with the values fields
1291 passed in as a hash list (similar to new(E<lt>fieldsE<gt>))
1292 B<(WARNING! not fully implemented)>
1293
1294 =item $sess->get(E<lt>varsE<gt> [,E<lt>callbackE<gt>])
1295
1296 do SNMP GET, multiple <vars> formats accepted.
1297 for syncronous operation <vars> will be updated
1298 with value(s) and type(s) and will also return
1299 retrieved value(s). If <callback> supplied method
1300 will operate asyncronously
1301
1302 =item $sess->fget(E<lt>varsE<gt> [,E<lt>callbackE<gt>])
1303
1304 do SNMP GET like 'get' and format the values according
1305 the handlers specified in $sess->{VarFormats} and
1306 $sess->{TypeFormats}
1307
1308 =item $sess->getnext(E<lt>varsE<gt> [,E<lt>callbackE<gt>])
1309
1310 do SNMP GETNEXT, multiple <vars> formats accepted,
1311 returns retrieved value(s), <vars> passed as arguments are
1312 updated to indicate next lexicographical <obj>,<iid>,<val>,
1313 and <type>
1314
1315 Note: simple string <vars>,(e.g., 'sysDescr.0')
1316 form is not updated. If <callback> supplied method
1317 will operate asyncronously
1318
1319 =item $sess->fgetnext(E<lt>varsE<gt> [,E<lt>callbackE<gt>])
1320
1321 do SNMP GETNEXT like getnext and format the values according
1322 the handlers specified in $sess->{VarFormats} and
1323 $sess->{TypeFormats}
1324
1325 =item $sess->set(E<lt>varsE<gt> [,E<lt>callbackE<gt>])
1326
1327 do SNMP SET, multiple <vars> formats accepted.
1328 the value field in all <vars> formats must be in a canonical
1329 format (i.e., well known format) to ensure unambiguous
1330 translation to SNMP MIB data value (see discussion of
1331 canonical value format <vars> description section),
1332 returns snmp_errno. If <callback> supplied method
1333 will operate asyncronously
1334
1335 =item $sess->getbulk(E<lt>non-repeatersE<gt>, E<lt>max-repeatersE<gt>, E<lt>varsE<gt>)
1336
1337 do an SNMP GETBULK, from the list of Varbinds, the single
1338 next lexico instance is fetched for the first n Varbinds
1339 as defined by <non-repeaters>. For remaining Varbinds,
1340 the m lexico instances are retrieved each of the remaining
1341 Varbinds, where m is <max-repeaters>.
1342
1343 =item $sess->bulkwalk(E<lt>non-repeatersE<gt>, E<lt>max-repeatersE<gt>, E<lt>varsE<gt> [,E<lt>callbackE<gt>])
1344
1345 Do a "bulkwalk" of the list of Varbinds.  This is done by
1346 sending a GETBULK request (see getbulk() above) for the
1347 Varbinds.  For each requested variable, the response is
1348 examined to see if the next lexico instance has left the
1349 requested sub-tree.  Any further instances returned for
1350 this variable are ignored, and the walk for that sub-tree
1351 is considered complete.
1352
1353 If any sub-trees were not completed when the end of the
1354 responses is reached, another request is composed, consisting
1355 of the remaining variables.  This process is repeated until
1356 all sub-trees have been completed, or too many packets have
1357 been exchanged (to avoid loops).
1358
1359 The bulkwalk() method returns an array containing an array of
1360 Varbinds, one for each requested variable, in the order of the
1361 variable requests.  Upon error, bulkwalk() returns undef and
1362 sets $sess->ErrorStr and $sess->ErrorNum.  If a callback is
1363 supplied, bulkwalk() returns the SNMP request id, and returns
1364 immediately.  The callback will be called with the supplied
1365 argument list and the returned variables list.
1366
1367 Note: Because the client must "discover" that the tree is
1368 complete by comparing the returned variables with those that
1369 were requested, there is a potential "gotcha" when using the
1370 max-repeaters value.  Consider the following code to print a
1371 list of interfaces and byte counts:
1372
1373     $numInts = $sess->get('ifNumber.0');
1374     ($desc, $in, $out) = $sess->bulkwalk(0, $numInts,
1375                   [['ifDescr'], ['ifInOctets'], ['ifOutOctets']]);
1376
1377     for $i (0..($numInts - 1)) {
1378         printf "Interface %4s: %s inOctets, %s outOctets\n",
1379                   $$desc[$i]->val, $$in[$i]->val, $$out[$i]->val;
1380     }
1381
1382 This code will produce *two* requests to the agent -- the first
1383 to get the interface values, and the second to discover that all
1384 the information was in the first packet.  To get around this,
1385 use '$numInts + 1' for the max_repeaters value.  This asks the
1386 agent to include one additional (unrelated) variable that signals
1387 the end of the sub-tree, allowing bulkwalk() to determine that
1388 the request is complete.
1389
1390 =back
1391
1392 =head1 SNMP::TrapSession
1393
1394 $sess = new SNMP::Session(DestHost => 'host', ...)
1395
1396 supports all applicable fields from SNMP::Session
1397 (see above)
1398
1399 =head2 SNMP::TrapSession methods
1400
1401 =over
1402
1403 =item $sess->trap(enterprise, agent, generic, specific, uptime, <vars>)
1404
1405     $sess->trap(enterprise=>'.1.3.6.1.4.1.2021', # or 'ucdavis' [default]
1406                 agent => '127.0.0.1', # or 'localhost',[dflt 1st intf on host]
1407                 generic => specific,  # can be omitted if 'specific' supplied
1408                 specific => 5,        # can be omitted if 'generic' supplied
1409                 uptime => 1234,       # dflt to localhost uptime (0 on win32)
1410                 [[ifIndex, 1, 1],[sysLocation, 0, "here"]]); # optional vars
1411                                                              # always last
1412
1413 =item trap(oid, uptime, <vars>) - v2 format
1414
1415     $sess->trap(oid => 'snmpRisingAlarm',
1416                 uptime => 1234,
1417                 [[ifIndex, 1, 1],[sysLocation, 0, "here"]]); # optional vars
1418                                                              # always last
1419
1420 =back
1421
1422 =head1 Acceptable variable formats:
1423
1424 <vars> may be one of the following forms:
1425
1426 =over
1427
1428 =item SNMP::VarList
1429
1430 represents an array of MIB objects to get or set,
1431 implemented as a blessed reference to an array of
1432 SNMP::Varbinds, (e.g., [<varbind1>, <varbind2>, ...])
1433
1434 =item SNMP::Varbind
1435
1436 represents a single MIB object to get or set, implemented as
1437 a blessed reference to a 4 element array;
1438 [<obj>, <iid>, <val>, <type>].
1439
1440 =over
1441
1442 =item <obj>
1443
1444 one of the following forms:
1445
1446 =over
1447
1448 =item 1)
1449
1450 leaf identifier (e.g., 'sysDescr') assumed to be
1451 unique for practical purposes
1452
1453 =item 2)
1454
1455 fully qualified identifier (e.g.,
1456 '.iso.org.dod.internet.mgmt.mib-2.system.sysDescr')
1457
1458 =item 3)
1459
1460 fully qualified, dotted-decimal, numeric OID (e.g.,
1461 '.1.3.6.1.2.1.1.1')
1462
1463 =back
1464
1465 =item <iid>
1466
1467 the dotted-decimal, instance identifier. for
1468 scalar MIB objects use '0'
1469
1470 =item <val>
1471
1472 the SNMP data value retrieved from or being set
1473 to the agents MIB. for (f)get(next) operations
1474 <val> may have a variety of formats as determined by
1475 session and package settings. However for set
1476 operations the <val> format must be canonical to
1477 ensure unambiguous translation. The canonical forms
1478 are as follows:
1479
1480 =over
1481
1482 =item OBJECTID
1483
1484 dotted-decimal (e.g., .1.3.6.1.2.1.1.1)
1485
1486 =item OCTETSTR
1487
1488 perl scalar containing octets
1489
1490 =item INTEGER
1491
1492 decimal signed integer (or enum)
1493
1494 =item NETADDR
1495
1496 dotted-decimal
1497
1498 =item IPADDR
1499
1500 dotted-decimal
1501
1502 =item COUNTER
1503
1504 decimal unsigned integer
1505
1506 =item COUNTER64
1507
1508 decimal unsigned integer
1509
1510 =item GAUGE
1511
1512 decimal unsigned integer
1513
1514 =item UINTEGER
1515
1516 decimal unsigned integer
1517
1518 =item TICKS
1519
1520 decimal unsigned integer
1521
1522 =item OPAQUE
1523
1524 perl scalar containing octets
1525
1526 =item NULL
1527
1528 perl scalar containing nothing
1529
1530 =back
1531
1532 =item <type>
1533
1534 SNMP data type (see list above), this field is
1535 populated by 'get' and 'getnext' operations. In
1536 some cases the programmer needs to populate this
1537 field when passing to a 'set' operation. this
1538 field need not be supplied when the attribute
1539 indicated by <tag> is already described by loaded
1540 Mib modules. for 'set's, if a numeric OID is used
1541 and the object is not currently in the loaded Mib,
1542 the <type> field must be supplied
1543
1544 =back
1545
1546 =item simple string
1547
1548 light weight form of <var> used to 'set' or 'get' a
1549 single attribute without constructing an SNMP::Varbind.
1550 stored in a perl scalar, has the form '<tag>.<iid>',
1551 (e.g., 'sysDescr.0'). for 'set' operations the value
1552 is passed as a second arg. Note: This argument form is
1553 not updated in get[next] operations as are the other forms.
1554
1555 =back
1556
1557 =head1 Acceptable callback formats
1558
1559 <callback> may be one of the following forms:
1560
1561 =over
1562
1563 =item without arguments
1564
1565 =over
1566
1567 =item \&subname
1568
1569 =item sub { ... }
1570
1571 =back
1572
1573 =item or with arguments
1574
1575 =over
1576
1577 =item [ \&subname, $arg1, ... ]
1578
1579 =item [ sub { ... }, $arg1, ... ]
1580
1581 =item [ "method", $obj, $arg1, ... ]
1582
1583 =back
1584
1585 =back
1586
1587 callback will be called when response is received or timeout
1588 occurs. the last argument passed to callback will be a
1589 SNMP::VarList reference. In case of timeout the last argument
1590 will be undef.
1591
1592 =over
1593
1594 =item &SNMP::MainLoop([<timeout>, [<callback>]])
1595
1596 to be used with async SNMP::Session
1597 calls. MainLoop must be called after initial async calls
1598 so return packets from the agent will not be processed.
1599 If no args suplied this function enters an infinite loop
1600 so program must be exited in a callback or externally
1601 interupted. If <timeout(sic)
1602
1603 =item &SNMP::finish()
1604
1605 This function, when called from an SNMP::MainLoop() callback
1606 function, will cause the current SNMP::MainLoop() to return
1607 after the callback is completed.  finish() can be used to
1608 terminate an otherwise-infinite MainLoop.  A new MainLoop()
1609 instance can then be started to handle further requests.
1610
1611 =back
1612
1613 =head1 SNMP package variables and functions
1614
1615 =over
1616
1617 =item $SNMP::VERSION
1618
1619 the current version specifier (e.g., 3.1.0)
1620
1621 =item $SNMP::auto_init_mib
1622
1623 default '1', set to 0 to disable automatic reading
1624 of the MIB upon session creation. set to non-zero
1625 to call initMib at session creation which will result
1626 in MIB loading according to UCD env. variables (see
1627 man mib_api)
1628
1629 =item $SNMP::verbose
1630
1631 default '0', controls warning/info output of
1632 SNMP module, 0 => no output, 1 => enables warning/info
1633 output from SNMP module itself (is also controlled
1634 by SNMP::debugging - see below)
1635
1636 =item $SNMP::use_long_names
1637
1638 default '0', set to non-zero to enable the use of
1639 longer Mib identifiers. see translateObj. will also
1640 influence the formatting of <tag> in varbinds returned
1641 from 'getnext' operations. Can be set on a per session
1642 basis (UseLongNames)
1643
1644 =item $SNMP::use_sprint_value
1645
1646 default '0', set to non-zero to enable formatting of
1647 response values using the snmp libraries snprint_value
1648 function. can also be set on a per session basis (see
1649 UseSprintValue) Note: returned values may not be
1650 suitable for 'set' operations
1651
1652 =item $SNMP::use_enums
1653
1654 default '0',set non-zero to return values as enums and
1655 allow sets using enums where appropriate. integer data
1656 will still be accepted for set operations. can also be
1657 set on a per session basis (see UseEnums)
1658
1659 =item $SNMP::use_numeric
1660
1661 default to '0',set to non-zero to have <tags> for 'get'
1662 methods returned as numeric OID's rather than descriptions.
1663 UseLongNames will be set so that the entire OID will be
1664 returned.  Set on a per-session basis (see UseNumeric).
1665
1666 =item $SNMP::save_descriptions
1667
1668 default '0',set non-zero to have mib parser save
1669 attribute descriptions. must be set prior to mib
1670 initialization
1671
1672 =item $SNMP::debugging
1673
1674 default '0', controlls debugging output level
1675 within SNMP module and libsnmp
1676
1677 =over
1678
1679 =item 1
1680
1681 enables 'SNMP::verbose' (see above)
1682
1683 =item 2
1684
1685 level 1 plus snmp_set_do_debugging(1)
1686
1687 =item 3
1688
1689 level 2 plus snmp_set_dump_packet(1)
1690
1691 =back
1692
1693 =item $SNMP::dump_packet
1694
1695 default '0', set [non-]zero to independently set
1696 snmp_set_dump_packet()
1697
1698 =back
1699
1700 =head1 %SNMP::MIB
1701
1702 a tied hash to access parsed MIB information. After
1703 the MIB has been loaded this hash allows access to
1704 to the parsed in MIB meta-data(the structure of the
1705 MIB (i.e., schema)). The hash returns blessed
1706 references to SNMP::MIB::NODE objects which represent
1707 a single MIB attribute. The nodes can be fetched with
1708 multiple 'key' formats - the leaf name (e.g.,sysDescr)
1709 or fully/partially qualified name (e.g.,
1710 system.sysDescr) or fully qualified numeric OID. The
1711 returned node object supports the following fields:
1712
1713 =over
1714
1715 =item objectID
1716
1717 dotted decimal fully qualified OID
1718
1719 =item label
1720
1721 leaf textual identifier (e.g., 'sysDescr')
1722
1723 =item subID
1724
1725 leaf numeric OID component of objectID (e.g., '1')
1726
1727 =item moduleID
1728
1729 textual identifier for module (e.g., 'RFC1213-MIB')
1730
1731 =item parent
1732
1733 parent node
1734
1735 =item children
1736
1737 array reference of children nodes
1738
1739 =item nextNode
1740
1741 next lexico node B<(BUG!does not return in lexico order)>
1742
1743 =item type
1744
1745 returns application type (see getType for values)
1746
1747 =item access
1748
1749 returns ACCESS (ReadOnly, ReadWrite, WriteOnly,
1750 NoAccess, Notify, Create)
1751
1752 =item status
1753
1754 returns STATUS (Mandatory, Optional, Obsolete,
1755 Deprecated)
1756
1757 =item syntax
1758
1759 returns 'textualConvention' if defined else 'type'
1760
1761 =item textualConvention
1762
1763 returns TEXTUAL-CONVENTION
1764
1765 =item units
1766
1767 returns UNITS
1768
1769 =item hint
1770
1771 returns HINT
1772
1773 =item enums
1774
1775 returns hash ref {tag => num, ...}
1776
1777 =item ranges
1778
1779 returns array ref of hash ref [{low => num, high => num}, ...]
1780
1781 =item description
1782
1783 returns DESCRIPTION ($SNMP::save_descriptions must
1784 be set prior to MIB initialization/parsing)
1785
1786 =back
1787
1788 =head1 MIB Functions
1789
1790 =over
1791
1792 =item &SNMP::setMib(<file>)
1793
1794 allows dynamic parsing of the mib and explicit
1795 specification of mib file independent of enviroment
1796 variables. called with no args acts like initMib,
1797 loading MIBs indicated by environment variables (see
1798 ucd mib_api docs). passing non-zero second arg
1799 forces previous mib to be freed and replaced
1800 B<(Note: second arg not working since freeing previous
1801 Mib is more involved than before)>.
1802
1803 =item &SNMP::initMib()
1804
1805 calls library init_mib function if Mib not already
1806 loaded - does nothing if Mib already loaded. will
1807 parse directories and load modules according to
1808 environment variables described in UCD documentations.
1809 (see man mib_api, MIBDIRS, MIBS, MIBFILE(S), etc.)
1810
1811 =item &SNMP::addMibDirs(<dir>,...)
1812
1813 calls library add_mibdir for each directory
1814 supplied. will cause directory(s) to be added to
1815 internal list and made available for searching in
1816 subsequent loadModules calls
1817
1818 =item &SNMP::addMibFiles(<file>,...)
1819
1820 calls library read_mib function. The file(s)
1821 supplied will be read and all Mib module definitions
1822 contained therein will be added to internal mib tree
1823 structure
1824
1825 =item &SNMP::loadModules(<mod>,...)
1826
1827 calls library read_module function. The
1828 module(s) supplied will be searched for in the
1829 current mibdirs and and added to internal mib tree
1830 structure. Passing special <mod>, 'ALL', will cause
1831 all known modules to be loaded.
1832
1833 =item &SNMP::unloadModules(<mod>,...)
1834
1835 B<*Not Implemented*>
1836
1837 =item &SNMP::translateObj(<var>[,arg])
1838
1839 will convert a text obj tag to an OID and
1840 vice-versa. any iid suffix is retained numerically.
1841 default behaviour when converting a numeric OID
1842 to text form is to return leaf indentifier only
1843 (e.g.,'sysDescr') but when $SNMP::use_long_names
1844 is non-zero or a non-zero second arg is supplied
1845 will return longer textual identifier. If no Mib
1846 is loaded when called and $SNMP::auto_init_mib is
1847 enabled then the Mib will be loaded. Will return
1848 'undef' upon failure.
1849
1850 =item &SNMP::getType(<var>)
1851
1852 return SNMP data type for given textual identifier
1853 OBJECTID, OCTETSTR, INTEGER, NETADDR, IPADDR, COUNTER
1854 GAUGE, TIMETICKS, OPAQUE, or undef
1855
1856 =item &SNMP::mapEnum(<var>)
1857
1858 converts integer value to enumertion tag defined
1859 in Mib or converts tag to integer depending on
1860 input. the function will return the corresponding
1861 integer value *or* tag for a given MIB attribute
1862 and value. The function will sense which direction
1863 to perform the conversion. Various arg formats are
1864 supported
1865
1866 =over
1867
1868 =item $val = SNMP::mapEnum($varbind);
1869
1870 where $varbind is SNMP::Varbind or equiv.
1871 note: $varbind will be updated
1872
1873 =item $val = SNMP::mapEnum('ipForwarding', 'forwarding');
1874
1875 =item $val = SNMP::mapEnum('ipForwarding', 1);
1876
1877 =back
1878
1879 =back
1880
1881 =head1 Exported SNMP utility functions
1882
1883 Note: utility functions do not support async operation yet.
1884
1885 =over
1886
1887 =item &snmp_get()
1888
1889 takes args of SNMP::Session::new followed by those of
1890 SNMP::Session::get
1891
1892 =item &snmp_getnext()
1893
1894 takes args of SNMP::Session::new followed by those of
1895 SNMP::Session::getnext
1896
1897 =item &snmp_set()
1898
1899 takes args of SNMP::Session::new followed by those of
1900 SNMP::Session::set
1901
1902 =item &snmp_trap()
1903
1904 takes args of SNMP::TrapSession::new followed by those of
1905 SNMP::TrapSession::trap
1906
1907 =back
1908
1909 =head1 Trouble Shooting
1910
1911 If problems occur there are number areas to look at to narrow down the
1912 possibilities.
1913
1914 The first step should be to test the UCD SNMP installation
1915 independently from the Perl5 SNMP interface.
1916
1917 Try running the apps from the UCD SNMP distribution.
1918
1919 Make sure your agent (snmpd) is running and properly configured with
1920 read-write access for the community you are using.
1921
1922 Ensure that your MIBs are installed and enviroment variables are set
1923 appropriately (see man mib_api)
1924
1925 Be sure to remove old ucd-snmp installations and ensure headers and
1926 libraries from old CMU installations are not being used by mistake.
1927
1928 If the problem occurs during compilation/linking check that the snmp
1929 library being linked is actually the UCD SNMP library (there have been
1930 name conflicts with existing snmp libs).
1931
1932 Also check that the header files are correct and up to date.
1933
1934 Sometimes compiling the UCD SNMP library with
1935 'position-independent-code' enabled is required (HPUX specifically).
1936
1937 If you cannot resolve the problem you can post to
1938 comp.lang.perl.modules or
1939 net-snmp-users@net-snmp-users@lists.sourceforge.net
1940
1941 please give sufficient information to analyze the problem (OS type,
1942 versions for OS/Perl/UCD/compiler, complete error output, etc.)
1943
1944 =head1 Acknowledments
1945
1946 Many thanks to all those who supplied patches, suggestions and
1947 feedback.
1948
1949  Joe Marzot (the original author)
1950  Wes Hardaker and the net-snmp-coders
1951  Dave Perkins
1952  Marcel Wiget
1953  David Blackburn
1954  John Stofell
1955  Gary Hayward
1956  Claire Harrison
1957  Achim Bohnet
1958  Doug Kingston
1959  Jacques Vidrine
1960  Carl Jacobsen
1961  Wayne Marquette
1962  Scott Schumate
1963  Michael Slifcak
1964  Perl5 Porters
1965
1966 Apologies to any/all who's patch/feature/request was not mentioned or
1967 included - most likely it was lost when paying work intruded on my
1968 fun. Please try again if you do not see a desired feature. This may
1969 actually turn out to be a decent package with such excellent help and
1970 the fact that I have more time to work on it than in the past.
1971
1972 =head1 AUTHOR
1973
1974 bugs, comments, questions to net-snmp-users@lists.sourceforge.net
1975
1976 =head1 Copyright
1977
1978      Copyright (c) 1995-2000 G. S. Marzot. All rights reserved.
1979      This program is free software; you can redistribute it and/or
1980      modify it under the same terms as Perl itself.
1981
1982      Copyright (c) 2001-2002 Networks Associates Technology, Inc.  All
1983      Rights Reserved.  This program is free software; you can
1984      redistribute it and/or modify it under the same terms as Perl
1985      itself.
1986 =cut