aboutsummaryrefslogtreecommitdiffstats
path: root/include/FixedSNMP.pm
blob: 1ea308966a84a78b1d7d8e1fda1851e124ea1095 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# A bugfix to the gettable functions of SNMP.pm, that deals properly
# with bulk responses being overridden. Original copyright:
#
#     Copyright (c) 1995-2006 G. S. Marzot. All rights reserved.
#     This program is free software; you can redistribute it and/or
#     modify it under the same terms as Perl itself.
#
# To use, just "use FixedSNMP;" and then use SNMP::Session as usual.

use strict;
use warnings;
use SNMP;

package FixedSNMP::Session;

sub _gettable_do_it() {
    my ($this, $vbl, $parse_indexes, $textnode, $state) = @_;

    my ($res);

    $vbl = $_[$#_] if ($state->{'options'}{'callback'});

    my $num_vbls = scalar @$vbl;
    my $num_stopconds = scalar @{$state->{'stopconds'}};

    while ($num_vbls > 0 && !$this->{ErrorNum}) {
        my @found_eof = (0) x $num_stopconds;

	for (my $i = 0; $i <= $#$vbl; $i++) {
	    my $row_oid = SNMP::translateObj($vbl->[$i][0]);
	    my $row_text = $vbl->[$i][0];
	    my $row_index = $vbl->[$i][1];
	    my $row_value = $vbl->[$i][2];
	    my $row_type = $vbl->[$i][3];

            my $stopcond_num = $i % $num_stopconds;
            my $stopcond = $state->{'stopconds'}[$stopcond_num];
	    if ($row_oid !~ /^\Q$stopcond\E/ || $row_value eq 'ENDOFMIBVIEW') {
                $found_eof[$stopcond_num] = 1;
            } else {

		if ($row_type eq "OBJECTID") {

		    # If the value returned is an OID, translate this
		    # back in to a textual OID

		    $row_value = SNMP::translateObj($row_value);

		}

		# continue past this next time

		$state->{'varbinds'}[$stopcond_num] = [ $row_text, $row_index ];

		# Place the results in a hash

		$state->{'result_hash'}{$row_index}{$row_text} = $row_value;
	    }
	}

	my @newstopconds = ();
        my @newvarbinds = ();
        for (my $i = 0; $i < $num_stopconds; ++$i) {
            unless ($found_eof[$i]) {
                push @newstopconds, $state->{'stopconds'}[$i];
                push @newvarbinds, $state->{'varbinds'}[$i];
            }
	}
	if ($#newstopconds == -1) {
	    last;
	}
	$state->{'varbinds'} = \@newvarbinds;
	$state->{'stopconds'} = \@newstopconds;
	$vbl = $state->{'varbinds'};
        $num_vbls = scalar @newvarbinds;
        $num_stopconds = scalar @newstopconds;

        #
        # if we've been configured with a callback, then call the
        # sub-functions with a callback to our own "next" processing
        # function (_gettable_do_it).  or else call the blocking method and
        # call the next processing function ourself.
        #
	if ($state->{'options'}{'callback'}) {
	    if ($this->{Version} ne '1' && !$state->{'options'}{'nogetbulk'}) {
		$res = $this->getbulk(0, $state->{'repeatcount'}, $vbl,
				      [\&_gettable_do_it, $this, $vbl,
				       $parse_indexes, $textnode, $state]);
	    } else {
		$res = $this->getnext($vbl,
				      [\&_gettable_do_it, $this, $vbl,
				       $parse_indexes, $textnode, $state]);
	    }
	    return;
	} else {
	    if ($this->{Version} ne '1' && !$state->{'options'}{'nogetbulk'}) {
		$res = $this->getbulk(0, $state->{'repeatcount'}, $vbl);
	    } else {
		$res = $this->getnext($vbl);
	    }
	}
    }

    # finish up
    _gettable_end_routine($state, $parse_indexes, $textnode);

    # return the hash if no callback was specified
    if (!$state->{'options'}{'callback'}) {
	return($state->{'result_hash'});
    }

    #
    # if they provided a callback, call it
    #   (if an array pass the args as well)
    #
    if (ref($state->{'options'}{'callback'}) eq 'ARRAY') {
	my $code = shift @{$state->{'options'}{'callback'}};
	$code->(@{$state->{'options'}{'callback'}}, $state->{'result_hash'});
    } else {
	$state->{'options'}{'callback'}->($state->{'result_hash'});
    }
}

*FixedSNMP::Session::_gettable_end_routine = *SNMP::Session::_gettable_end_routine;
*SNMP::Session::_gettable_do_it = *FixedSNMP::Session::_gettable_do_it;