File Coverage

blib/lib/SNMP/Util.pm
Criterion Covered Total %
statement 4 6 66.6
branch n/a
condition n/a
subroutine 2 2 100.0
pod n/a
total 6 8 75.0


line stmt bran cond sub pod time code
1             package SNMP::Util;
2             ##
3             ##
4             ## Summary: This library contains basic methods for SNMP communications
5             ##
6             ## Description: This library contains a set of functions for handling snmp
7             ## communications
8             ##
9             ## Author: Wayne Marquette - 6/2/98 - New library
10              
11             ## Compiler directives.
12 1     1   2849 use strict;
  1         2  
  1         36  
13              
14             ## Module import.
15 1     1   1620 use SNMP;
  0            
  0            
16             use FileHandle qw(autoflush);
17             use SNMP::Util_env;
18             use vars qw($VERSION);
19             $VERSION = "1.8";
20              
21              
22             autoflush STDOUT;
23              
24             ## Initalize Globals
25             use vars qw($Delimiter $Max_log_level $Return_type);
26              
27             @Util::EXPORT_OK = qw (
28             index_get_array
29             index_set_array
30             log
31             print_array
32             );
33              
34             @Util::ISA = qw(Exporter);
35              
36              
37             ################################ Public Methods ###############################
38              
39              
40             sub new {
41             my($class, %args) = @_;
42             my(
43             $Comm_string,
44             $IP,
45             $device,
46             $errmode,
47             $mib_match,
48             $mib_filename,
49             $mib,
50             $poll,
51             $poll_timeout,
52             $retry,
53             $self,
54             $timeout,
55             $udp_port,
56             $verbose,
57             );
58              
59             ## Parse named args.
60             $verbose = 0;
61             foreach (keys %args) {
62             if (/^-community/i) {
63             $Comm_string = $args{$_};
64             }
65             elsif (/^-device/i || /^-dev/) {
66             $IP = $args{$_};
67             }
68             elsif (/^-port/i || /^-udp_port/) {
69             $udp_port = $args{$_};
70             }
71             elsif (/^-timeout/i) {
72             $timeout = $args{$_};
73             }
74             elsif (/^-retry/i) {
75             $retry = $args{$_};
76             }
77             elsif (/^-poll$/i) {
78             $poll = $args{$_};
79             }
80             elsif (/^-poll_timeout/i) {
81             $poll_timeout = $args{$_};
82             }
83             elsif (/^-errmode/i) {
84             $errmode = $args{$_};
85             }
86             elsif (/^-mib/i) { #Not used but leave here for compatability
87             $mib = $args{$_};
88             }
89             elsif (/^-verbose/i) {
90             $verbose = $args{$_};;
91             if ($verbose eq 'on'){
92             $verbose = 1;
93             }
94             elsif ($verbose eq 'off'){
95             $verbose = 0;
96             }
97             else{
98             $verbose = 0;
99             }
100             }
101             elsif (/^-delimiter/ || /^octet-delimit/){ # Change delimiter for octet string output
102             $Delimiter = $args{$_};
103             }
104             else {
105             die "Invalid argument - \"$_\"";
106             }
107             }
108              
109            
110             ## Create a new object.
111             $self = bless {}, $class;
112             $self->{IP} = $IP;
113             $self->{community} = $Comm_string;
114             $self->{timeout} = $timeout;
115             $self->{poll} = $poll;
116             $self->{poll_timeout} = $poll_timeout;
117             $self->{retry} = $retry;
118              
119              
120             # Set all defaults
121             if (!defined $self->{community} or $self->{community} eq '') {
122             $self->{community} = 'public';
123             }
124             if (!defined $self->{timeout} or $self->{timeout} eq '') {
125             $self->{timeout} = 5;
126             }
127             if (!defined $self->{retry} or $self->{retry} eq '') {
128             $self->{retry} = 3;
129             }
130              
131             if (!defined $self->{poll} or $self->{poll} eq '') {
132             $self->{poll} = 1;
133             }
134             elsif ($self->{poll} eq 'on') {
135             $self->{poll} = 1;
136             }
137             elsif ($self->{poll} eq 'off') {
138             $self->{poll} = 0;
139             }
140             else {
141             $self->{poll} = 1;
142             }
143              
144             if (!defined $self->{poll_timeout} or $self->{poll_timeout} eq '') {
145             $self->{poll_timeout} = 5;
146             }
147              
148             ## Convert sec to microseconds
149             $self->{timeout} = $self->{timeout} * 1000000;
150              
151             ## Turn verbose messages on.
152             if ($verbose){
153             $SNMP::verbose = 1;
154             }
155             else{
156             $SNMP::verbose = 0;
157             }
158            
159             $Return_type = 'array';
160            
161             # Initialize mib
162             &SNMP::initMib();
163              
164             ## Create new SNMP Session.
165             $self->{snmp} = new SNMP::Session(DestHost => $self->{IP},
166             Community => $self->{community},
167             Timeout => $self->{timeout},
168             Retries => $self->{retry},
169             RemotePort => $self->{udp_port},
170             UseEnums => 1,
171             );
172              
173             return undef unless (defined $self->{snmp});
174             ## Set the error mode.
175             if (defined $errmode) {
176             $self->errmode($errmode);
177             }
178             else {
179             ## Default to return.
180             $self->errmode('return');
181             }
182              
183             ## Return the new object.
184             $self;
185             } # end sub new
186              
187              
188             sub ping_check_exit {
189             my($self) = @_;
190             my(
191             $IP,
192             $pingres,
193             $result,
194             $snmp,
195             $save_log_level,
196             $save_snmp,
197             $save_poll,
198             @pingres,
199             );
200            
201             ## Variable init.
202             $IP = $self->{IP};
203              
204             $save_log_level = $SNMP::Util::Max_log_level;
205             $save_poll = $self->{poll};
206             $save_snmp = $self->{snmp};
207              
208             # Turn logging off
209             $SNMP::Util::Max_log_level = 'none';
210              
211             $self->{poll} = 0;
212              
213              
214             $self->{snmp} = new SNMP::Session(DestHost => $IP,
215             Community => $self->{community},
216             Timeout => 2000000,
217             Retries => 0,
218             RemotePort => $self->{udp_port},
219             UseEnums => 1,
220             );
221              
222             $pingres = $self->get('v','sysUpTime.0');
223              
224             $self->{poll} = $save_poll;
225             $self->{snmp} = $save_snmp;
226              
227             # Change logging back to default
228             $SNMP::Util::Max_log_level = $save_log_level;
229              
230             if (!$self->error && $pingres =~ /^\d+/){
231             return 1;
232             }
233             else {
234             &log('fail',"Cannot reach device $IP - Test Failed\n");
235             return;
236             }
237             } # end sub ping_check_exit
238              
239              
240             sub ping_check {
241             my($self) = @_;
242             my(
243             $IP,
244             $pingres,
245             $result,
246             $save_log_level,
247             $save_poll,
248             $save_snmp,
249             $snmp,
250             @pingres,
251             );
252              
253             $IP = $self->{IP};
254              
255             $save_log_level = $SNMP::Util::Max_log_level;
256             $save_poll = $self->{poll};
257             $save_snmp = $self->{snmp};
258              
259             $self->{poll} = 0;
260              
261             # Turn logging off
262             $SNMP::Util::Max_log_level = 'none';
263              
264             $self->{snmp} = new SNMP::Session(DestHost => $IP,
265             Community => $self->{community},
266             Timeout => 2000000,
267             Retries => 0,
268             RemotePort => $self->{udp_port},
269             UseEnums => 1,
270             );
271              
272             $pingres = $self->get('v','sysUpTime.0');
273              
274             # Change logging back to default
275             $SNMP::Util::Max_log_level = $save_log_level;
276              
277             $self->{poll} = $save_poll;
278             $self->{snmp} = $save_snmp;
279              
280             if (!$self->error && $pingres =~ /^\d+/){
281             return 1;
282             }
283             else {
284             return;
285             }
286             } # endsub ping_check
287              
288              
289             sub poll_device {
290             my($self) = @_;
291             my(
292             $IP,
293             $elapsed_time,
294             $end_time,
295             $get_result,
296             $poll_timeout,
297             $result,
298             $uptime,
299             @uptime,
300             );
301              
302             ## Variable init.
303             my $time_min = 0;
304             my $time_sec = 0;
305             my $start_time = time;
306             my $stop = 0;
307              
308             $IP = $self->{IP};
309              
310             $poll_timeout = $self->{poll_timeout};
311              
312             if (!defined $poll_timeout || $poll_timeout eq '') {
313             $poll_timeout = 5;
314             }
315              
316             $elapsed_time = '0:0';
317             &log('fail',"\n");
318             while ($time_min < $poll_timeout){
319             &log('fail',"Waiting for device $IP to respond at $elapsed_time (min:sec) \r");
320             $result = $self->ping_check;
321             $end_time = time;
322             $time_sec = $end_time - $start_time;
323             $time_min = $time_sec / 60;
324             $time_sec = $time_sec % 60;
325             $elapsed_time = sprintf("%2d:%2d",$time_min,$time_sec);
326             if ($result){
327             &log('status',"\nDevice $IP is now responding at $elapsed_time (min:sec)\n\n");
328             return 1;
329             }
330             #sleep 5;
331             }
332             &log('fail',"\nDevice $IP did not respond after $poll_timeout minutes \n\n");
333             # Return fail exit status
334             return 0;
335             } # end sub poll_device
336            
337              
338             sub poll_devices {
339             my($self, @IP_array) = @_;
340             my($IP);
341            
342             foreach $IP (@IP_array) {
343             $self->poll_device($IP);
344             }
345             } # end sub poll_devices
346              
347             ## Usage: $snmp->get($self,$format,@oid_list);
348             ##
349             ## Description: This subroutine will simply do an snmpget and verify that
350             ## no error occured and returns the result (referenced).
351             sub get {
352             my($self, @args) = @_;
353             my(
354             $error,
355             $error_index,
356             $format,
357             $hash,
358             $oid_list,
359             $poll,
360             $poll_result,
361             $return_type,
362             $snmp,
363             $value,
364             $vars,
365             $IP,
366             %args,
367             @oid_list,
368             @values,
369             );
370            
371             ## Determine if caller is using positional format or dashed args.
372             ## If first arg start with a dash, all args must be of that format.
373             if ($args[0] !~ /^-/) {
374             ## Arguments were supplied as positional.
375             ($format, @oid_list) = @args;
376             }
377             else {
378             ## Parse named args.
379             %args = @args;
380             foreach (keys %args) {
381             if (/^-format$/) {
382             $format = $args{$_};
383             }
384             elsif (/^-oids$/) {
385             $oid_list = $args{$_};
386             (ref $oid_list eq 'ARRAY')
387             or die "Value of \"-oids\" must be an array ref";
388             }
389             else {
390             die "Invalid argument to SNMP::Util::get: \"$_\"";
391             }
392             }
393             }
394             $oid_list = \@oid_list unless defined $oid_list;
395              
396              
397             ## Variable init.
398             $poll = $self->{poll};
399             $IP = $self->{IP};
400              
401             $snmp = $self->{snmp};
402              
403             ## Clear any previous errors.
404             $self->error_reset;
405              
406             $vars = &build_get_var_list($oid_list);
407              
408             &log('debug',"\nsnmpget $IP @$oid_list\n");
409              
410             $snmp->get($vars);
411              
412             $error = $snmp->{ErrorStr};
413             $error_index = $snmp->{ErrorInd};
414              
415             $return_type = $Return_type;
416            
417              
418             if ($error ne ''){
419             &log_error($self,'get',$error,$oid_list,$error_index);
420             if ($poll && $error =~ /timeout/i ){
421             ## Poll for device if timeout retry times
422             $poll_result = $self->poll_device
423             or return $self->error("oper: ", "SNMP::Util::poll_device failed\n");
424             $snmp->get($vars);
425            
426             $error = $snmp->{ErrorStr};
427             if ($error ne ''){
428             &log_error($self,'get',$error,$oid_list,$error_index);
429             return $self->error("oper: ","SNMP::Util::get failed $error\n");
430             }
431             else{
432             if ($return_type eq 'array'){
433             @values = &format_array($format,$vars);
434             if (@values == 1){
435             $value = $values[0];
436             return($value);
437             }
438             return (@values);
439             }
440             elsif ($return_type eq 'hash'){
441             $hash = &format_hash($format,$vars);
442             return ($hash);
443             }
444             }
445             }
446             else{
447             return $self->error("oper: ","SNMP::Util::get failed $error\n");
448             }
449             }
450             else{
451             if ($return_type eq 'array'){
452             @values = &format_array($format,$vars);
453             if (@values == 1){
454             $value = $values[0];
455             return($value);
456             }
457             return (@values);
458             }
459             elsif ($return_type eq 'hash'){
460             $hash = &format_hash($format,$vars);
461             return ($hash);
462             }
463             }
464              
465             } # end sub get
466              
467             sub get_hash {
468             my($self, @args) = @_;
469              
470             my($hash);
471              
472             $SNMP::Util::Return_type = 'hash';
473             $hash = $self->get(@args);
474             $SNMP::Util::Return_type = 'array';
475              
476             $hash;
477            
478             } # end sub get_hash
479              
480              
481             sub set {
482             my($self, @args) = @_;
483             my(
484             $error,
485             $error_index,
486             $format,
487             $i,
488             $oid_list,
489             $poll,
490             $poll_result,
491             $snmp,
492             $vars,
493             $IP,
494             %args,
495             @oid_list,
496             @values,
497             );
498              
499             ## Determine if caller is using positional format or dashed args.
500             ## If first arg start with a dash, all args must be of that format.
501             if ($args[0] !~ /^-/) {
502             ## Arguments were supplied as positional.
503             @oid_list = @args;
504             }
505             else {
506             ## Parse named args.
507             %args = @args;
508             foreach (keys %args) {
509             if (/^-oids$/) {
510             $oid_list = $args{$_};
511             (ref $oid_list eq 'ARRAY')
512             or die "Value of \"-oids\" must be an array ref";
513             }
514             else {
515             die "Invalid argument to Snmp::set:: \"$_\"";
516             }
517             }
518             }
519              
520            
521             $oid_list = \@args unless defined $oid_list;
522              
523             ## Variable init.
524             $poll = $self->{poll};
525             $IP = $self->{IP};
526              
527             $snmp = $self->{snmp};
528              
529             ## Clear any previous errors.
530             $self->error_reset;
531              
532             $vars = &build_set_var_list($oid_list);
533             if (!defined $vars){
534             &log_error($self,'set','oid list incomplete',$oid_list,$error_index);
535             return $self->error("oper: ", "build_set_var_list failed\n");
536             }
537             &log('debug',"\nsnmpset $IP @$oid_list\n");
538             $snmp->set($vars);
539              
540             $error = $snmp->{ErrorStr};
541             $error_index = $snmp->{ErrorInd};
542              
543             if ($error ne ''){
544             &log_error($self,'set',$error,$oid_list,$error_index);
545             if ($poll && $error =~ /timeout/i){
546             ## Poll for device if timeout retry times
547             $poll_result = $self->poll_device
548             or return $self->error("oper: ", "SNMP::Util::poll_device failed\n");
549             $snmp->set($vars);
550            
551             $error = $snmp->{ErrorStr};
552             if ($error ne ''){
553             &log_error($self,'set',$error,$oid_list,$error_index);
554             return $self->error("oper: ", "SNMP::Util::snmp set failed $error\n");
555             }
556             }
557             else{
558             return $self->error("oper: ", "SNMP::Util::snmp set failed $error\n");
559             }
560             }
561             else{
562             return 1;
563             }
564            
565              
566              
567             } # end sub set
568              
569             sub set_get {
570             my($self, @args) = @_;
571             my(
572             $error,
573             $error_index,
574             $fail,
575             $format,
576             $get_value,
577             $i,
578             $index,
579             $oid_hash,
580             $oid_list,
581             $poll,
582             $poll_result,
583             $set_oid,
584             $set_value,
585             $snmp,
586             $vars,
587             $IP,
588             %args,
589             @get_oids,
590             @get_result,
591             @oid_list,
592             @oids,
593             @set_array,
594             @values,
595             );
596            
597             ## Determine if caller is using positional format or dashed args.
598             ## If first arg start with a dash, all args must be of that format.
599             if ($args[0] !~ /^-/) {
600             ## Arguments were supplied as positional.
601             ($format, @oid_list) = @args;
602             }
603             else {
604             ## Parse named args.
605             %args = @args;
606             foreach (keys %args) {
607             if (/^-oids$/) {
608             $oid_list = $args{$_};
609             (ref $oid_list eq 'ARRAY')
610             or die "Value of \"-oids\" must be an array ref";
611             }
612             else {
613             die "Invalid argument to SNMP::Util::set_get: \"$_\"";
614             }
615             }
616             }
617              
618             $oid_list = \@args unless defined $oid_list;
619              
620             ## Variable init.
621             $poll = $self->{poll};
622             $IP = $self->{IP};
623              
624             $snmp = $self->{snmp};
625              
626             ## Clear any previous errors.
627             $self->error_reset;
628              
629             $oid_hash = &set_list_to_names_and_oids($oid_list);
630             @set_array = @{$oid_hash->{names}};
631              
632             # Check if the second value is a enum or integer
633             if ($set_array[1] =~ /^[a-zA-Z]+/){
634             $format = 'ne';
635             }
636             else{
637             $format = 'nv';
638             }
639              
640              
641             @get_oids = ();
642             for ($i = 0; $i<= $#set_array; $i+=2){
643             push @get_oids,$set_array[$i];
644             }
645              
646             $vars = &build_set_var_list($oid_list);
647              
648             &log('debug',"\nsnmpset $IP @$oid_list\n");
649             $snmp->set($vars);
650              
651             $error = $snmp->{ErrorStr};
652             $error_index = $snmp->{ErrorInd};
653            
654             $fail = 0;
655             if ($error ne ''){
656             &log_error($self,'set',$error,$oid_list,$error_index);
657             if ($poll && $error =~ /timeout/i){
658             ## Poll for device if timeout retry times
659             $poll_result = $self->poll_device
660             or return $self->error("oper: ", "SNMP::Util::poll_device failed\n");
661             $snmp->set($vars);
662            
663             $error = $snmp->{ErrorStr};
664             if ($error ne ''){
665             &log_error($self,'set',$error,$oid_list,$error_index);
666             return $self->error("oper: ", "SNMP::Util::snmp set failed $error\n");
667             }
668             else{
669             @values = &format_array($format,$vars);
670             return (@values);
671             }
672             }
673             else{
674             return $self->error("oper: ", "SNMP::Util::snmp set failed $error\n",);
675             }
676             }
677             else{
678             @get_result = $self->get($format,@get_oids);
679            
680             for ($i = 0; $i <= $#set_array; $i+=2){
681             $set_oid = $set_array[$i];
682             $set_value = $set_array[$i+1];
683             if ($set_oid ne $get_result[$i]){
684             &log('fail',"set - @set_array\n");
685             &log('fail',"get - @get_result\n");
686             $fail = 1;
687             }
688             if ($set_value ne $get_result[$i+1]){
689             &log('fail',"set - @set_array\n");
690             &log('fail',"get - @get_result\n");
691             $fail = 1;
692             }
693             }
694             if (!$fail){
695             return 1;
696             }
697             else{
698             return ;
699             }
700             }
701             } # end sub set
702              
703            
704             sub next {
705             my($self, @args) = @_;
706             my(
707             $error,
708             $error_index,
709             $format,
710             $oid_list,
711             $poll,
712             $poll_result,
713             $snmp,
714             $vars,
715             $IP,
716             %args,
717             @oid_list,
718             @values,
719             );
720            
721             ## Determine if caller is using positional format or dashed args.
722             ## If first arg start with a dash, all args must be of that format.
723             if ($args[0] !~ /^-/) {
724             ## Arguments were supplied as positional.
725             ($format, @oid_list) = @args;
726             }
727             else {
728             ## Parse named args.
729             %args = @args;
730             foreach (keys %args) {
731             if (/^-format$/) {
732             $format = $args{$_};
733             }
734             elsif (/^-oids$/) {
735             $oid_list = $args{$_};
736             (ref $oid_list eq 'ARRAY')
737             or die "Value of \"-oids\" must be an array ref";
738             }
739             else {
740             die "Invalid argument to SNMP::Util::next: \"$_\"";
741             }
742             }
743             }
744             $oid_list = \@oid_list unless defined $oid_list;
745              
746             ## Variable init.
747             $poll = $self->{poll};
748             $IP = $self->{IP};
749              
750             $snmp = $self->{snmp};
751              
752             ## Clear any previous errors.
753             $self->error_reset;
754              
755             $vars = &build_get_var_list($oid_list);
756            
757             &log('debug',"\nsnmpnext $IP @$oid_list\n");
758             $snmp->getnext($vars);
759              
760             $error = $snmp->{ErrorStr};
761             $error_index = $snmp->{ErrorInd};
762              
763             if ($error ne ''){
764             &log_error($self,'next',$error,$oid_list,$error_index);
765             if ($poll && $error =~ /timeout/i){
766             ## Poll for device if timeout retry times
767             $poll_result = $self->poll_device
768             or return $self->error("oper: ", "SNMP::Util::poll_device failed\n");
769            
770            
771             $snmp->getnext($vars);
772            
773             $error = $snmp->{ErrorStr};
774             if ($error ne ''){
775             &log_error($self,'next',$error,$oid_list,$error_index);
776             return $self->error("oper: ", "SNMP::Util::next failed $error\n");
777              
778             }
779             else{
780             @values = &format_array($format,$vars);
781             return (@values);
782             }
783             }
784             else{
785             return $self->error("oper: ", "SNMP::Util::next failed $error\n");
786             }
787             }
788             else{
789             @values = &format_array($format,$vars);
790             return (@values);
791             }
792            
793              
794              
795             } # end sub get
796              
797              
798             sub get_set_restore {
799             my($self, $range, @oid_list) = @_;
800             my(
801             $IP,
802             $value,
803             $oid,
804             $value,
805             $value_hi,
806             $value_lo,
807             @range,
808             @restore_oid_list,
809             @set_oid_list,
810             @value_array,
811             );
812              
813             ## Variable init.
814             $IP = $self->{IP};
815              
816             @restore_oid_list = $self->get('nv',@oid_list)
817             or return;
818              
819             eval "\@range = ($range)";
820              
821              
822             # Set the variable to all valid values
823             foreach $value (@range){
824             @set_oid_list = ();
825             foreach $oid (@oid_list) {
826             push @set_oid_list, $oid, $value;
827             }
828             $self->set_get(@set_oid_list)
829             or return;
830             &log('status',"Setting @set_oid_list\r");
831             }
832              
833              
834             $self->set(@restore_oid_list)
835             or return;
836             &log('status',"\nRestoring @restore_oid_list \n");
837              
838             return 1;
839             } # end sub get_set_range_restore
840              
841              
842             sub walk {
843             my($self, @args) = @_;
844             my(
845             $error,
846             $error_index,
847             $format,
848             $hash,
849             $i,
850             $instance,
851             $loop,
852             $loop_retry,
853             $loop_stuck,
854             $name,
855             $name_indexed,
856             $oid,
857             $oid_hash,
858             $oid_list,
859             $oid_indexed,
860             $poll,
861             $poll_result,
862             $print,
863             $return_type,
864             $snmp,
865             $temp_hash,
866             $temp_value,
867             $test,
868             $type,
869             $vars,
870             $value,
871             $IP,
872             %args,
873             @patterns,
874             @oid_list,
875             @oids,
876             @tmp_oid_list,
877             @tmp_patterns,
878             @values,
879             @walk_values,
880             );
881            
882             ## Determine if caller is using positional format or dashed args.
883             ## If first arg start with a dash, all args must be of that format.
884             if ($args[0] !~ /^-/) {
885             ## Arguments were supplied as positional.
886             ($format, @oid_list) = @args;
887             }
888             else {
889             ## Parse named args.
890             %args = @args;
891             $print = 0;
892             foreach (keys %args) {
893             if (/^-format$/) {
894             $format = $args{$_};
895             }
896             elsif (/^-oids$/) {
897             $oid_list = $args{$_};
898             (ref $oid_list eq 'ARRAY')
899             or die "Value of \"-oids\" must be an array ref";
900             }
901             elsif (/^-print$/) {
902             $print = $args{$_};
903             if ($print eq 'on'){
904             $print = 1;
905             }
906             elsif ($print eq 'off'){
907             $print = 0;
908             }
909             else{
910             $print = 0;
911             }
912             }
913             else {
914             die "Invalid argument to SNMP::Util::walk: \"$_\"";
915             }
916             }
917             }
918              
919             $oid_list = \@oid_list unless defined $oid_list;
920              
921             ## Variable init.
922             $poll = $self->{poll};
923             $IP = $self->{IP};
924              
925             $snmp = $self->{snmp};
926              
927             $return_type = $Return_type;
928              
929             ## Clear any previous errors.
930             $self->error_reset;
931              
932             @walk_values = ();
933             &log('debug',"\nsnmpwalk $IP @$oid_list\n");
934              
935             #Convert oid list to hash and then array
936             $oid_hash = &get_list_to_names_and_oids($oid_list);
937             @oid_list = @{$oid_hash->{names}};
938             @oids = @{$oid_hash->{oids}};
939             @patterns = @oids;
940              
941             $loop = 1;
942             $loop_retry = 1;
943             $loop_stuck = 1;
944             while (@oid_list){
945             $oid_list = \@oid_list;
946             $vars = &build_get_var_list($oid_list);
947             $snmp->getnext($vars);
948            
949             $error = $snmp->{ErrorStr};
950             $error_index = $snmp->{ErrorInd};
951            
952             if ($error ne ''){
953             &log_error($self,'walk',$error,$oid_list,$error_index);
954            
955             if ($poll && $error =~ /timeout/i){
956             ## Poll for device if timeout retry times
957             $poll_result = $self->poll_device
958             or return $self->error("oper: ", "SNMP::Util::poll_device failed\n");
959            
960            
961             $snmp->getnext($vars);
962            
963             $error = $snmp->{ErrorStr};
964             if ($error ne ''){
965             &log_error($self,'walk',$error,$oid_list,$error_index);
966             return $self->error("oper: ", "SNMP::Util::walk failed $error\n");
967             }
968             }
969             else{
970             if ($loop > 1 && $error =~ /nosuch/i){ #End of mib??
971             &log("fail","\nnosuchName error End of Mib??\n\n");
972             }
973             else{
974             return $self->error("oper: ", "SNMP::Util::walk failed $error\n");
975             }
976             }
977             }
978              
979             # Check for timeout and retry if it's not the first next
980             if ($error =~ /timeout/i){
981             if ($loop == 1){
982             &log_error($self,'walk',$error,$oid_list,$error_index);
983             return $self->error("oper: ", "SNMP::Util::walk timeout\n");
984             }
985             elsif ($loop > 1){ #Retry on timeout if not first time through loop
986             if ($loop_retry < 4){ #
987             $loop_retry++;
988             next unless ($loop_retry == 3);
989             &log_error($self,'walk',$error,$oid_list,$error_index);
990             return $self->error("oper: ", "SNMP::Util::walk timeout\n");
991             }
992             }
993             }
994             elsif (@tmp_oid_list && ($oid_list[0] eq $tmp_oid_list[0]) && $loop_stuck < 11){ # Abort infinite loop
995             $loop_stuck++;
996             next unless ($loop_stuck == 10);
997             &log_error($self,'walk','Exiting infinite loop',$oid_list,$error_index);
998             return $self->error("fatal: ","Exiting infinite loop\n");
999             }
1000              
1001             $loop_stuck = 1;
1002             $loop_retry = 1;
1003             $test = 1;
1004              
1005             @tmp_oid_list = @oid_list;
1006             @tmp_patterns = @patterns;
1007             @patterns = ();
1008             @oid_list = ();
1009             for ($i = 0; $i<= $#tmp_oid_list; $i++){
1010             $name = $vars->[$i]->[0];
1011             $temp_value = $vars->[$i]->[2];
1012             $type = $vars->[$i]->[3];
1013             $oid = &SNMP::translateObj($name);
1014             $oid =~ s/\.//;
1015             $instance = $vars->[$i]->[1];
1016             if (!defined $instance || $instance eq ''){
1017             $name_indexed = $name;
1018             $oid_indexed = $oid;
1019             }
1020             else{
1021             $name_indexed = "$name.$instance";
1022             $oid_indexed = "$oid.$instance";
1023             }
1024              
1025              
1026             if (defined $tmp_patterns[$i] && $oid_indexed =~ /^$tmp_patterns[$i]\./){
1027             push @oid_list,$name_indexed;
1028             push @patterns,$tmp_patterns[$i];
1029             if ($return_type eq 'hash'){
1030             $value = &convert_value($format,$name,$type,$temp_value);
1031             $hash->{$name}{$instance} = $value;
1032             }
1033             }
1034             else{
1035             $test = 0;
1036             }
1037             }
1038             if ($test){
1039             if ($loop > 1 && $error =~ /nosuch/i){ ##End of mib ??
1040             return @walk_values;
1041             }
1042             if ($return_type eq 'array'){
1043             @values = &format_array($format,$vars);
1044             print "@values\n" if ($print);
1045             push @walk_values,@values;
1046             }
1047             }
1048             $loop++;
1049             }
1050             if ($return_type eq 'array'){
1051             return(@walk_values);
1052             }
1053             elsif ($return_type eq 'hash'){
1054             return($hash);
1055             }
1056             else{
1057             return(@walk_values);
1058             }
1059            
1060            
1061            
1062             return @walk_values;
1063            
1064             } # end sub walk
1065              
1066             sub walk_hash {
1067             my($self, @args) = @_;
1068              
1069             my($hash);
1070              
1071             $SNMP::Util::Return_type = 'hash';
1072             $hash = $self->walk(@args);
1073             $SNMP::Util::Return_type = 'array';
1074              
1075             $hash;
1076            
1077             } # end sub walk_hash
1078              
1079             sub poll_value {
1080             my($self, %args) = @_;
1081             my(
1082             $IP,
1083             $delay,
1084             $elapsed_time,
1085             $format,
1086             $get_value,
1087             $instance,
1088             $mon_time,
1089             $oid,
1090             $name,
1091             $time,
1092             $time_out,
1093             $transition_time,
1094             $value,
1095             @value,
1096             $stop,
1097             );
1098              
1099             foreach (keys %args) {
1100             if (/^-oid/i) {
1101             $oid = $args{$_};
1102             }
1103             elsif (/^-value/i || /^-state/i) {
1104             $value = $args{$_};
1105             }
1106             elsif (/^-montime/i || /^-mon_time/) {
1107             $mon_time = $args{$_};
1108             }
1109             elsif (/^-instance/){
1110             $instance = $args{$_};
1111             }
1112             elsif (/^-timeout/i || /^-time_out/) {
1113             $time_out = $args{$_};
1114             }
1115             elsif (/^-delay/i) {
1116             $delay = $args{$_};
1117             }
1118             }
1119              
1120             if (ref($value) eq 'ARRAY'){
1121             @value = @$value;
1122             }
1123              
1124             ## Variable init.
1125             $IP = $self->{IP};
1126             $time_out = 120 unless defined $time_out;
1127             $mon_time = 0 unless defined $mon_time;
1128             $delay = 1 unless defined $delay;
1129              
1130             &log('fail',"\n");
1131             if ($value =~ /^[a-zA-Z]+/) {
1132             $format = 'e';
1133             }
1134             else {
1135             $format = 'v';
1136             }
1137              
1138             if (defined $instance){
1139             ($name,$oid) = &get_name_and_oid($oid);
1140             $name = "$name.$instance";
1141             $get_value = $self->get($format, $name);
1142             }
1143             else{
1144             ($name,$instance) = ($oid =~ /^(\w+)\.(.*)$/);
1145             ($name,$oid) = &get_name_and_oid($name);
1146             $name = "$name.$instance";
1147             $get_value = $self->get($format, $name);
1148             }
1149            
1150             $get_value = '' unless defined $get_value;
1151             $time = time;
1152             $elapsed_time = 0;
1153             # Check if the get value equals the desired value
1154             $stop = 0;
1155             if (@value){
1156             if (grep(/$get_value/,@value)){
1157             &log('status',"\n$name = $get_value at elapsed_time ($elapsed_time seconds) for device $IP\n");
1158             $stop = 1;
1159             }
1160             }
1161             elsif ($get_value eq $value) {
1162             &log('status',"\n$name = $get_value at elapsed_time ($elapsed_time seconds) for device $IP\n");
1163             $stop = 1;
1164             }
1165             unless ($stop) {
1166             while (!$stop) {
1167             $get_value = $self->get($format, $name);
1168             $get_value = '' unless defined $get_value;
1169            
1170             $elapsed_time = time - $time;
1171             if ($elapsed_time > $time_out) {
1172             if (@value){
1173             &log('fail',"\n$name is not [@value] for device $IP at elapsed_time ($elapsed_time seconds)\n");
1174             }
1175             else{
1176             &log('fail',"\n$name is not $value for device $IP at elapsed_time ($elapsed_time seconds)\n");
1177             }
1178             return $self->error("oper: ", "SNMP::Util::poll_value failed\n");
1179             $value = $get_value;
1180             return;
1181             }
1182             if (@value){
1183             if (grep(/$get_value/,@value)){
1184             &log('status',"\n$name $get_value = [@value] at elapsed_time ($elapsed_time seconds) for device $IP\n");
1185             $stop = 1;
1186             }
1187             else{
1188             &log('status',"$name = $get_value at elapsed_time ($elapsed_time seconds) for device $IP \r");
1189             }
1190             }
1191             elsif (defined $get_value && $get_value eq $value) {
1192             &log('status',"\n$name is now $get_value at elapsed_time ($elapsed_time seconds) for device $IP\n");
1193             $stop = 1;
1194             }
1195             elsif (defined $get_value && $get_value ne '') {
1196             &log('status',"$name = $get_value at elapsed_time ($elapsed_time seconds) for device $IP \r");
1197             }
1198             sleep $delay;
1199             }
1200             }
1201             $transition_time = $elapsed_time;
1202             if ($transition_time == 0) {
1203             $transition_time = 0.5;
1204             }
1205            
1206             $time = time;
1207             $elapsed_time = 0;
1208             while ($elapsed_time < $mon_time) {
1209             $get_value = $self->get($format, $name);
1210             $elapsed_time = time - $time;
1211             if (@value){
1212             if (grep(/$get_value/,@value)){
1213             &log('status',"Monitoring $name = $get_value at time $elapsed_time seconds \r");
1214             }
1215             else{
1216             &log('fail',"\n $name = $get_value should be [@value] at $elapsed_time seconds\n");
1217             return $self->error("oper: ", "SNMP::Util::poll_value Monitoring failed\n");
1218             }
1219             }
1220             elsif (defined $get_value && $get_value eq $value) {
1221             &log('status',"Monitoring $name = $get_value at $elapsed_time seconds \r");
1222             $stop = 0;
1223             }
1224             elsif(defined $get_value && $get_value ne $value) {
1225             &log('fail',"\n $name = $get_value should be $value at $elapsed_time seconds\n");
1226             return $self->error("oper: ", "SNMP::Util::poll_value Monitoring failed\n");
1227             }
1228             sleep $delay;
1229             }
1230             &log('status',"\n");
1231              
1232             return($transition_time);
1233             } # end sub poll_value
1234              
1235              
1236             ################################ Private Methods ##############################
1237              
1238              
1239              
1240              
1241             sub build_get_var_list{
1242             my($args) = @_;
1243             my(
1244             $i,
1245             $index,
1246             $instance,
1247             $name,
1248             $name_indexed,
1249             $start_index,
1250             $vars,
1251             @args,
1252             @oid_list,
1253             @var_list,
1254             );
1255              
1256             @args = @$args;
1257              
1258             @var_list = ();
1259              
1260             $start_index = 0;
1261             if ($args[0] =~ /^\d+/ && $args[0] !~ /^1.3.6.1/){
1262             $index = $args[0];
1263             $start_index ++;
1264             }
1265             elsif ($args[0] eq 'index'){
1266             $index = $args[1];
1267             $start_index+=2;
1268             }
1269             for ($i = $start_index; $i <= $#args; $i++){
1270             if (defined $index){ # Index is defined in hash
1271             $name = $args[$i];
1272             push @var_list, ["$name", "$index"];
1273             }
1274             elsif ($args[$i] =~ /^[a-zA-Z]+/ && $args[$i] =~ /^(\w+)\.\d+/){ # Index is contained in name (not applicable to oids)
1275             ($name,$instance) = ($args[$i] =~ /^(\w+)\.(.*)$/);
1276             push @var_list, ["$name", "$instance"];
1277             }
1278             else{ # Instance is either passed after name or there is none
1279             $name = $args[$i];
1280             if (defined $args[$i+1]){
1281             $instance = $args[$i+1];
1282             if ($instance =~ /^\d+/ && $instance !~ /^1.3.6.1/){ # Intance is an index
1283             push @var_list, ["$name", "$instance"];
1284             $i++;
1285             }
1286             else{ ## Instance is name or an oid with no index (for walk only)
1287             push @var_list, ["$name", ""], ["$instance", ""];
1288             $i++;
1289             }
1290             }
1291             else{ #no instance
1292             push @var_list, ["$name", ""];
1293             }
1294             }
1295             }
1296             $vars = new SNMP::VarList(@var_list);
1297             $vars;
1298             }
1299              
1300             sub build_set_var_list{
1301             my($args) = @_;
1302            
1303             my(
1304             $i,
1305             $index,
1306             $instance,
1307             $oid,
1308             $name,
1309             $name_indexed,
1310             $start_index,
1311             $type,
1312             $value,
1313             $vars,
1314             @args,
1315             @oid_list,
1316             @var_list,
1317             );
1318            
1319            
1320             @args = @$args;
1321             @var_list = ();
1322              
1323             $start_index = 0;
1324             if ($args[0] =~ /^\d+/ && $args[0] !~ /^1.3.6.1/){
1325             $index = $args[0];
1326             $start_index ++;
1327             }
1328             elsif ($args[0] eq 'index'){
1329             $index = $args[1];
1330             $start_index+=2;
1331             }
1332              
1333             for ($i = $start_index; $i <= $#args; $i++){
1334             if (defined $index){ # Index may be passed for oids or names
1335             $name = $args[$i];
1336             ($name,$oid) = &get_name_and_oid($name);
1337             $value = $args[$i+1];
1338             $type = &SNMP::getType($name);
1339              
1340             # Convert octets before sent out
1341             $value = &pack_octet($value) if (!defined $SNMP::MIB{$name}{textualConvention} && $type =~ /octet/i);
1342             push @var_list, ["$name","$index","$value"];
1343             $i++;
1344             }
1345             elsif ($args[$i] =~ /^[a-zA-Z]+/ && $args[$i] =~ /^(\w+)\.\d*/ ){ #Format only allowed for names
1346             ($name,$instance) = ($args[$i] =~ /^(\w+)\.(.*)$/);
1347             return if ($instance eq '');
1348             ($name,$oid) = &get_name_and_oid($name);
1349             $value = $args[$i+1];
1350             return if (!defined $value);
1351             $type = &SNMP::getType($name);
1352              
1353             # Convert octets before sent out
1354             $value = &pack_octet($value) if (!defined $SNMP::MIB{$name}{textualConvention} && $type =~ /octet/i);
1355             push @var_list, ["$name","$instance","$value"];
1356             $i ++;
1357             }
1358             else{ #Use this case for names and oids
1359             $name = $args[$i];
1360             $instance = $args[$i+1];
1361             $value = $args[$i+2];
1362             ($name,$oid) = &get_name_and_oid($name);
1363             $type = &SNMP::getType($name);
1364            
1365             # Convert octets before sent out
1366             $value = &pack_octet($value) if (!defined $SNMP::MIB{$name}{textualConvention} && $type =~ /octet/i);
1367             push @var_list, ["$name","$instance","$value"];
1368             $i+=2;
1369             }
1370            
1371             }
1372              
1373             $vars = new SNMP::VarList(@var_list);
1374             $vars;
1375             }
1376              
1377             sub pack_octet{
1378             my($value) = @_;
1379             my(
1380             $byte,
1381             $packed_val,
1382             @octets,
1383             @values,
1384             );
1385            
1386             @values = split(' ', $value);
1387             foreach $byte (@values) {
1388             push @octets, hex($byte);
1389             }
1390             $packed_val = pack('C*', @octets);
1391             }
1392              
1393             sub unpack_octet{
1394             my($name,$value) = @_;
1395              
1396             my(
1397             $octet,
1398             $octet_string,
1399             @octets,
1400             $tc,
1401             $delimiter,
1402             );
1403              
1404             $octet_string = '';
1405             if (!defined $Delimiter){
1406             $delimiter = ' ';
1407             }
1408             else{
1409             $delimiter = $Delimiter;
1410             }
1411              
1412             ##Check textual convection for type of octet-string
1413             $tc = $SNMP::MIB{$name}{textualConvention};
1414             if (!defined $tc){ #Real type is octet-string
1415             @octets = unpack("C*", $value);
1416             if (@octets){
1417             foreach $octet (@octets){
1418             $octet = sprintf("%2.2x",$octet);
1419             $octet_string = "$octet_string$delimiter$octet";
1420             }
1421             }
1422             else{
1423             $octet_string = '';
1424             }
1425             $value = $octet_string;
1426             }
1427             elsif ($tc =~ /addr/i) {
1428             @octets = unpack("C*", $value);
1429             if (@octets){
1430             foreach $octet (@octets){
1431             $octet = sprintf("%2.2x",$octet);
1432             $octet_string = "$octet_string$delimiter$octet";
1433             }
1434             }
1435             else{
1436             $octet_string = '';
1437             }
1438             $value = $octet_string
1439             }
1440             $value =~ s/^$delimiter//;
1441             $value;
1442             }
1443              
1444             ## Add the indexes to the array for the snmpget
1445             ## and enumrations to values.
1446             ##
1447             ## Input : array of (oid-names)
1448             ## Output: array of (oids)
1449             sub index_get_array {
1450             my($index, @names) = @_;
1451             my(
1452             $indexed_name,
1453             $name,
1454             @indexed_names,
1455             );
1456              
1457             foreach $name (@names) {
1458             $indexed_name = "$name.$index";
1459             push @indexed_names,$indexed_name;
1460             }
1461              
1462             return (@indexed_names);
1463             } # end index_get_array
1464              
1465             sub log_error{
1466             my($self,$func,$error,$oid_list,$error_index)= @_;
1467              
1468             my(
1469             $IP,
1470             $Comm_string,
1471             @oids,
1472             @names,
1473             $oid_hash,
1474             );
1475              
1476             $IP = $self->{IP};
1477             $Comm_string = $self->{community};
1478              
1479             if ($func =~ /set/){
1480             $oid_hash = &set_list_to_names_and_oids($oid_list);
1481             @oids = @{$oid_hash->{oids}};
1482             @names = @{$oid_hash->{names}};
1483             }
1484             else{
1485             $oid_hash = &get_list_to_names_and_oids($oid_list);
1486             @oids = @{$oid_hash->{oids}};
1487             @names = @{$oid_hash->{names}};
1488             }
1489              
1490             if ($error ne ''){
1491             if ($error =~ /timeout/i){
1492             &log('fail',"\n\n$func Timeout\n");
1493             &log('fail',"snmp$func $IP $Comm_string @oids\n");
1494             &log('fail',"snmp$func $IP $Comm_string @names\n");
1495             $self->error_detail('',"$func Timeout\n","snmp$func $IP $Comm_string @oids\n","snmp$func $IP $Comm_string @names\n");
1496             }
1497             else{
1498             &log('fail',"\n\n$func $error\n");
1499             &log('fail',"snmp$func $IP $Comm_string @oids\n");
1500             &log('fail',"snmp$func $IP $Comm_string @names\n");
1501             &log('fail',"snmp error index = $error_index\n");
1502             $self->error_detail($error_index,"$func $error\n",$error_index,"snmp$func $IP $Comm_string @oids\n","snmp$func $IP $Comm_string @names\n","snmp error index = $error_index\n");
1503             }
1504             }
1505             }
1506              
1507             ## Add the indexes to the array for an snmpset
1508             ##
1509             ## Input: index and array
1510             ## Output: array of indexed names with corresponding type and value
1511             sub index_set_array {
1512             my($index, @names) = @_;
1513             my(
1514             $i,
1515             $indexed_name,
1516             $name,
1517             @indexed_names,
1518             );
1519              
1520             for ($i = 0; $i <= $#names; $i+=3) {
1521             # if the oid is a name
1522             $indexed_name = "$names[$i].$index";
1523             push @indexed_names, $indexed_name, $names[$i+1], $names[$i+2];
1524             }
1525              
1526             return (@indexed_names);
1527             } # end sub index_set_array
1528              
1529             ##Convert names to oids
1530             sub get_list_to_names_and_oids{
1531             my($args) = @_;
1532             my(
1533             $index,
1534             $i,
1535             $instance,
1536             $name,
1537             $name2,
1538             $oid,
1539             $oid2,
1540             $oid_name,
1541             @oid_names,
1542             @oids,
1543             $name_indexed,
1544             $start_index,
1545             $hash,
1546             @args,
1547             );
1548              
1549            
1550             @args = @$args;
1551              
1552             @oids = ();
1553             @oid_names = ();
1554             $start_index = 0;
1555             if ($args[0] =~ /^\d+/ && $args[0] !~ /^1.3.6.1/){
1556             $index = $args[0];
1557             $start_index ++;
1558             }
1559             elsif ($args[0] eq 'index'){
1560             $index = $args[1];
1561             $start_index+=2;
1562             }
1563             for ($i = $start_index; $i <= $#args; $i++){
1564             if (defined $index){
1565             $name = $args[$i];
1566             $instance = $index;
1567             ($name,$oid) = &get_name_and_oid($name);
1568             $oid_name = "$name.$instance";
1569             $oid = "$oid.$instance";
1570             push @oid_names,$oid_name;
1571             push @oids,$oid;
1572             }
1573             elsif ($args[$i] =~ /^(\w+)\.\d+/ && $args[$i] =~ /^[a-zA-Z]+/){ # only allowed for names not oids
1574             ($name,$instance) = ($args[$i] =~ /^(\w+)\.(.*)$/);
1575             ($name,$oid) = &get_name_and_oid($name);
1576              
1577             $oid_name = "$name.$instance";
1578             $oid = "$oid.$instance";
1579             push @oid_names,$oid_name;
1580             push @oids,$oid;
1581             }
1582             else{ # Instance is either passed after name or there is none
1583             $name = $args[$i];
1584            
1585             $instance = $args[$i+1] if defined $args[$i+1];
1586             if (!defined $instance){ #No instance
1587             ($name,$oid) = &get_name_and_oid($name);
1588             push @oid_names,$name;
1589             push @oids,$oid;
1590             }
1591             elsif ($instance =~ /^\d+/ && $instance !~ /^1.3.6.1/){
1592             $instance = $args[$i+1];
1593             ($name,$oid) = &get_name_and_oid($name);
1594             $oid_name = "$name.$instance";
1595             $oid = "$oid.$instance";
1596             push @oid_names,$oid_name;
1597             push @oids,$oid;
1598             $i++;
1599             }
1600             else{ ## Instance is name or oid (no instance passed (for walk only))
1601             ($name,$oid) = &get_name_and_oid($name);
1602             if (defined $args[$i+1]){
1603             $name2 = $args[$i+1];
1604             ($name2,$oid2) = &get_name_and_oid($name2);
1605             push @oid_names,$name,$name2;
1606             push @oids,$oid,$oid2;
1607             $i++;
1608             }
1609             else{
1610             push @oids,$oid;
1611             push @oid_names,$name;
1612             }
1613             }
1614             }
1615             }
1616             $hash->{names} = [@oid_names];
1617             $hash->{oids} = [@oids];
1618              
1619             $hash;
1620             }##Convert names to oids
1621              
1622             sub set_list_to_names_and_oids{
1623             my($args) = @_;
1624             my(
1625             $index,
1626             $i,
1627             $instance,
1628             $name,
1629             $oid,
1630             $type,
1631             $value,
1632             $temp_value,
1633             $oid_name,
1634             @oid_names,
1635             @oids,
1636             @oid_names,
1637             $name_indexed,
1638             $start_index,
1639             $hash,
1640             @args,
1641             );
1642              
1643             @args = @$args;
1644              
1645             $start_index = 0;
1646             if ($args[0] =~ /^\d+/ && $args[0] !~ /^1.3.6.1/){
1647             $index = $args[0];
1648             $start_index ++;
1649             }
1650             elsif ($args[0] eq 'index'){
1651             $index = $args[1];
1652             $start_index+=2;
1653             }
1654              
1655             @oids = ();
1656             @oid_names = ();
1657             # Check if type field is passed for snmpset
1658             for ($i = $start_index; $i <= $#args; $i++){
1659             if (defined $index){
1660             $name = $args[$i];
1661             $instance = $index;
1662             $temp_value = $args[$i+1];
1663             return if (!defined $temp_value);
1664             ($name,$oid) = &get_name_and_oid($name);
1665             $type = &SNMP::getType($name);
1666             $i++;
1667             if ($temp_value =~ /^\d+/ && $type =~ /integer/i){
1668             $value = &SNMP::mapEnum($name,$temp_value);
1669             $value = $temp_value if (!defined $value || $value eq '');
1670             push @oid_names,"$name.$instance",$value;
1671             push @oids,"$oid.$instance",$temp_value;
1672             }
1673             elsif ($temp_value =~ /^[a-zA-Z]/ && $type =~ /integer/i){
1674             $value = &SNMP::mapEnum($name,$temp_value);
1675             $value = $temp_value if (!defined $value || $value eq '');
1676             push @oid_names,"$name.$instance",$temp_value;
1677             push @oids,"$oid.$instance",$value;
1678             }
1679             else{
1680             push @oid_names,"$name.$instance",$temp_value;
1681             push @oids,"$oid.$instance",$temp_value;
1682             }
1683             }
1684             elsif ($args[$i] =~ /^[a-zA-Z]+/ && $args[$i] =~ /^(\w+)\.\d*/ ){ # Use this case for names
1685             ($name,$instance) = ($args[$i] =~ /^(\w+)\.(.*)$/);
1686             return if (!defined $instance || $instance eq '');
1687             $temp_value = $args[$i+1];
1688             return if (!defined $temp_value);
1689             ($name,$oid) = &get_name_and_oid($name);
1690             $type = &SNMP::getType($name);
1691             $i++;
1692              
1693             if ($temp_value =~ /^\d+/ && $type =~ /integer/i){
1694             $value = &SNMP::mapEnum($name,$temp_value);
1695             $value = $temp_value if (!defined $value || $value eq '');
1696             push @oid_names,"$name.$instance",$value;
1697             push @oids,"$oid.$instance",$temp_value;
1698             }
1699             elsif ($temp_value =~ /^[a-zA-Z]/ && $type =~ /integer/i){
1700             $value = &SNMP::mapEnum($name,$temp_value);
1701             $value = $temp_value if (!defined $value || $value eq '');
1702             push @oid_names,"$name.$instance",$temp_value;
1703             push @oids,"$oid.$instance",$value;
1704             }
1705             else{
1706             push @oid_names,"$name.$instance",$temp_value;
1707             push @oids,"$oid.$instance",$temp_value;
1708             }
1709             }
1710             else{
1711             $name = $args[$i];
1712             $instance = $args[$i+1];
1713             $temp_value = $args[$i+2];
1714             ($name,$oid) = &get_name_and_oid($name);
1715             $type = &SNMP::getType($name);
1716             $i+=2;
1717             if ($temp_value =~ /^\d+/ && $type =~ /integer/i){
1718             $value = &SNMP::mapEnum($name,$temp_value);
1719             $value = $temp_value if (!defined $value || $value eq '');
1720             push @oid_names,"$name.$instance",$value;
1721             push @oids,"$oid.$instance",$temp_value;
1722             }
1723             elsif ($temp_value =~ /^[a-zA-Z]/ && $type =~ /integer/i){
1724             $value = &SNMP::mapEnum($name,$temp_value);
1725             $value = $temp_value if (!defined $value || $value eq '');
1726             push @oid_names,"$name.$instance",$temp_value;
1727             push @oids,"$oid.$instance",$value;
1728             }
1729             else{
1730             push @oid_names,"$name.$instance",$temp_value;
1731             push @oids,"$oid.$instance",$temp_value;
1732             }
1733             }
1734             }
1735              
1736             $hash->{names} = [@oid_names];
1737             $hash->{oids} = [@oids];
1738              
1739             $hash;
1740             }
1741              
1742              
1743             sub format_array {
1744             my($format, $vars) = @_;
1745             my(
1746             $enum,
1747             $i,
1748             $instance,
1749             $name,
1750             $name_instance,
1751             $number_values,
1752             $octet,
1753             $octet_string,
1754             $oid,
1755             $option,
1756             $tc,
1757             $status,
1758             $type,
1759             $temp_value,
1760             $value,
1761             @format,
1762             @octets,
1763             @result,
1764             );
1765            
1766             ## Variable init.
1767             @format = split('', $format);
1768              
1769             $number_values = @{$vars};
1770             @result = ();
1771             for ($i = 0; $i< $number_values; $i++){
1772             $name = $vars->[$i]->[0];
1773             ($name,$oid) = &get_name_and_oid($name);
1774             $instance = $vars->[$i]->[1];
1775             $name_instance = "$name.$instance";
1776             $temp_value = $vars->[$i]->[2];
1777             $type = $vars->[$i]->[3];
1778            
1779             foreach $option (@format) {
1780             if ($option eq 'o') {
1781             push @result, "$oid.$instance";
1782             next;
1783             }
1784             if ($option eq 'O') {
1785             push @result, "$oid";
1786             next;
1787             }
1788             if ($option eq 't') {
1789             push @result, $type;
1790             next;
1791             }
1792             if ($option eq 'v' || $option eq 'e'){
1793             $value = &convert_value($option,$name,$type,$temp_value);
1794             push @result, $value;
1795             next;
1796             }
1797             if ($option eq 'i') {
1798             push @result, $instance;
1799             next;
1800             }
1801             if ($option eq 'n') {
1802             push @result, $name_instance;
1803             next;
1804             }
1805             if ($option eq 'N') {
1806             push @result, $name;
1807             next;
1808             }
1809             }
1810             }
1811              
1812             return(@result);
1813              
1814             } # end sub format_array
1815              
1816             sub format_hash {
1817             my($format, $vars) = @_;
1818             my(
1819             $enum,
1820             $hash,
1821             $i,
1822             $instance,
1823             $name,
1824             $name_instance,
1825             $number_values,
1826             $octet,
1827             $octet_string,
1828             $oid,
1829             $option,
1830             $tc,
1831             $status,
1832             $type,
1833             $temp_value,
1834             $value,
1835             @format,
1836             @octets,
1837             @result,
1838             );
1839            
1840             ## Variable init.
1841             @format = split('', $format);
1842              
1843             $number_values = @{$vars};
1844             @result = ();
1845             for ($i = 0; $i< $number_values; $i++){
1846             $name = $vars->[$i]->[0];
1847             ($name,$oid) = &get_name_and_oid($name);
1848             $instance = $vars->[$i]->[1];
1849             $name_instance = "$name.$instance";
1850             $temp_value = $vars->[$i]->[2];
1851             $type = $vars->[$i]->[3];
1852              
1853             $value = &convert_value($format,$name,$type,$temp_value);
1854              
1855             $hash->{$name}{$instance} = $value;
1856              
1857             }
1858              
1859             $hash;
1860              
1861             } # end sub format_array
1862              
1863             sub convert_value{
1864             my($format,$name,$type,$temp_value) = @_;
1865              
1866             my($value);
1867              
1868             if ($format =~ /e/){
1869             #Convert the packed data to hex format (octet-string)
1870             if ($type =~ /octet/i){
1871             $value = &unpack_octet($name,$temp_value);
1872             }
1873             elsif ($type =~ /integer/i){
1874             $value = $temp_value;
1875             }
1876             elsif ($type =~ /ticks/i) {
1877             $value = &decode_uptime($temp_value);
1878             }
1879             else{
1880             $value = $temp_value;
1881             }
1882             }
1883             elsif ($format =~ /v/){
1884             if ($type =~ /integer/i && $temp_value =~ /^[a-zA-Z]/){
1885             $value = &SNMP::mapEnum($name,$temp_value);
1886             $value = $temp_value if (!defined $value || $value eq '');
1887             }
1888             elsif ($type =~ /octet/i){
1889             $value = &unpack_octet($name,$temp_value);
1890             }
1891             else{
1892             $value = $temp_value;
1893             }
1894             }
1895             $value;
1896             }
1897              
1898             sub get_name_and_oid{
1899             my($value) = @_;
1900            
1901             my(
1902             $oid,
1903             $name,
1904             @oid_name,
1905             );
1906            
1907             return if (!defined $value);
1908             if ($value =~ /^[a-zA-Z]+/){ #Value is a mib name not an oid
1909             $name = $value;
1910             $oid = &SNMP::translateObj($value);
1911             $oid =~ s/^\.//;
1912             }
1913             else{ # Value is an oid
1914             $oid = $value;
1915             $oid =~ s/^\.//;
1916             $name = &SNMP::translateObj($oid);
1917             }
1918              
1919             @oid_name = ($name,$oid);
1920             @oid_name;
1921             }
1922             sub print_array {
1923             my($format, @list) = @_;
1924             my(
1925             $count,
1926             $number_items,
1927             $string,
1928             $value,
1929             @number_items,
1930             );
1931              
1932             ## Variable init.
1933             @number_items = split('',$format);
1934             $number_items = @number_items;
1935             $count = 1;
1936             $string = '';
1937              
1938             foreach $value (@list) {
1939             $string = "$string $value";
1940             if ($count >= $number_items) {
1941             print "$string\n";
1942             $string = '';
1943             $count = 1;
1944             }
1945             else {
1946             $count ++;
1947             }
1948             }
1949             } # end sub print_array
1950              
1951              
1952              
1953             ##--------------------------------------------------------------------
1954             ## Usage: &decode_uptime($timetick)
1955             ## Description: decode an time tick data item
1956             ## Input: $timetick, encoded timetick
1957             ## Output: Time in days, hours:minute:seconds
1958             ##-------------------------------------------------------------------
1959             sub decode_uptime {
1960             my($uptime) = @_;
1961             my(
1962             $days,
1963             $hours,
1964             $minutes,
1965             $result,
1966             $seconds,
1967             );
1968              
1969             $uptime /= 100;
1970             $days = $uptime / (60 * 60 * 24);
1971             $uptime %= (60 * 60 * 24);
1972              
1973             $hours = $uptime / (60 * 60);
1974             $uptime %= (60 * 60);
1975              
1976             $minutes = $uptime / 60;
1977             $seconds = $uptime % 60;
1978              
1979             if ($days == 0) {
1980             $result = sprintf("%d:%02d:%02d", $hours, $minutes, $seconds);
1981             }
1982             elsif ($days == 1) {
1983             $result = sprintf("%d day, %d:%02d:%02d",
1984             $days, $hours, $minutes, $seconds);
1985             }
1986             else {
1987             $result = sprintf("%d days, %d:%02d:%02d",
1988             $days, $hours, $minutes, $seconds);
1989             }
1990              
1991             return $result;
1992             } # end sub decode_uptime
1993              
1994              
1995             sub log {
1996             my($log_level, $message) = @_;
1997              
1998             my(
1999             $max_log_level,
2000             );
2001              
2002             if (defined $SNMP::Util::Max_log_level){
2003             $max_log_level = $SNMP::Util::Max_log_level;
2004             }
2005             else{
2006             $max_log_level = $ENV{'MAX_LOG_LEVEL'};
2007             if (!defined $max_log_level || $max_log_level eq '') {
2008             $max_log_level = $ENV{'ATS_MAX_LOG_LEVEL'};
2009             }
2010             }
2011              
2012             $max_log_level = 2 unless defined $max_log_level;
2013             $log_level = 2 unless defined $log_level;
2014              
2015             $SNMP::Util::Max_log_level = $max_log_level unless defined $SNMP::Util::Max_log_level;
2016              
2017             ## Convert max_log_level text tags to numbers.
2018             if ($max_log_level =~ /none/i || $max_log_level =~ /off/i) {
2019             $max_log_level = 0;
2020             }
2021             elsif ($max_log_level =~ /fail/i) {
2022             $max_log_level = 1;
2023             }
2024             elsif ($max_log_level =~ /status/i) {
2025             $max_log_level = 2;
2026             }
2027             elsif ($max_log_level =~ /debug/i) {
2028             $max_log_level = 3;
2029             }
2030              
2031             ## Convert log_level text tags to numbers.
2032             if ($log_level =~ /none/i || $log_level =~ /off/i) {
2033             ## No logging
2034             $log_level = 0;
2035             }
2036             elsif ($log_level =~ /fail/i) {
2037             ## Failures only
2038             $log_level = 1;
2039             }
2040             elsif ($log_level =~ /status/i) {
2041             ## Failures and general status
2042             $log_level = 2;
2043             }
2044             elsif ($log_level =~ /debug/i) {
2045             ## Failures, status, and details
2046             $log_level = 3;
2047             }
2048              
2049             if ($log_level <= $max_log_level){
2050             print "$message";
2051             }
2052             } # end sub log
2053              
2054              
2055             ############################# Error Handling Methods #########################
2056              
2057              
2058             sub die {
2059             my(@msgs) = @_;
2060             my $prg;
2061              
2062             ## Get the program's name.
2063             $prg = $0;
2064             $prg =~ s#\s+.*$##; # truncate everything but first word
2065             $prg =~ s#^.*/##; # truncate leading path
2066              
2067             ## Print error message along w/ stack backtrace and then die.
2068             $Carp::CarpLevel = 1;
2069             &Carp::confess(join('', "$prg died: ", @msgs, "\n"));
2070             } # end sub die
2071              
2072              
2073             sub error {
2074             my($self, $errortype, @errormsgs) = @_;
2075              
2076              
2077             if (! defined $errortype) { # no arg given
2078             if ($self->{"errormsg"}) {
2079             return 1;
2080             }
2081             else {
2082             return '';
2083             }
2084             }
2085             else { # arg given
2086             ## Save error message.
2087             $self->{"errortype"} = $errortype;
2088             $self->{"errormsg"} = join '', @errormsgs;
2089              
2090             ## Die or return with error.
2091             if ($self->{errormode} ne "return") {
2092             &die($self->{"errormsg"});
2093             }
2094             else {
2095             return wantarray ? () : undef;
2096             }
2097             }
2098             } # end sub error
2099              
2100             sub error_detail {
2101             my($self,$error_index, @errormsg_detail) = @_;
2102              
2103             ## Save error message.
2104             push @errormsg_detail,"snmp error index = $error_index\n" if ($error_index ne '');
2105             $self->{"errormsg_detail"} = join '', @errormsg_detail;
2106            
2107             ## Die or return with error.
2108             if ($self->{errormode} ne "return") {
2109             &die($self->{"errormsg_detail"});
2110             }
2111             else {
2112             return wantarray ? () : undef;
2113             }
2114             } # end sub error
2115              
2116              
2117             sub error_index {
2118             my($self, $errortype, @errormsgs) = @_;
2119              
2120             if (! defined $errortype) { # no arg given
2121             if ($self->{"errormsg"}) {
2122             return 1;
2123             }
2124             else {
2125             return '';
2126             }
2127             }
2128             else { # arg given
2129             ## Save error message.
2130             $self->{"errortype"} = $errortype;
2131             $self->{"errormsg"} = join '', @errormsgs;
2132              
2133             ## Die or return with error.
2134             if ($self->{errormode} ne "return") {
2135             &die($self->{"errormsg"});
2136             }
2137             else {
2138             return wantarray ? () : undef;
2139             }
2140             }
2141             } # end sub error
2142              
2143              
2144             sub error_reset {
2145             my($self) = @_;
2146            
2147             ## Save error message.
2148             $self->{"errortype"} = "";
2149             $self->{"errormsg"} = "";
2150             $self->{"errormsg_detail"} = "";
2151              
2152             1;
2153             } # end sub error_reset
2154              
2155              
2156             sub errmode {
2157             my($self, $mode) = @_;
2158            
2159             if (defined $mode) {
2160             if ($mode =~ /^return$/i) {
2161             $self->{errormode} = "return";
2162             }
2163             else {
2164             $self->{errormode} = "die";
2165             }
2166             }
2167              
2168             return $self->{errormode};
2169             } # end sub errmode
2170              
2171              
2172             sub errmsg {
2173             my($self, $msg) = @_;
2174              
2175             if (defined $msg) {
2176             $self->{errormsg} = $msg;
2177             }
2178              
2179             return $self->{errormsg};
2180             } # end sub errmsg
2181              
2182             sub errmsg_detail {
2183             my($self, $msg) = @_;
2184              
2185             if (defined $msg) {
2186             $self->{errormsg_detail} = $msg;
2187             }
2188            
2189             return $self->{errormsg_detail};
2190             } # end sub errmsg
2191              
2192              
2193              
2194             sub errtype {
2195             my($self, $type) = @_;
2196            
2197             if (defined $type) {
2198             $self->{errortype} = $type;
2199             return '';
2200             }
2201              
2202             return $self->{errortype};
2203             } # end sub errtype
2204              
2205              
2206             1;
2207              
2208             __END__;