~ubuntu-branches/debian/lenny/smokeping/lenny

« back to all changes in this revision

Viewing changes to lib/Smokeping/probes/CiscoRTTMonDNS.pm

  • Committer: Bazaar Package Importer
  • Author(s): Niko Tyni
  • Date: 2006-10-26 21:45:56 UTC
  • mfrom: (1.2.2 upstream) (2.1.5 edgy)
  • Revision ID: james.westby@ubuntu.com-20061026214556-5jnpiesx4vdijmu6
* debian/patches/15_clean_makefile.dpatch:
  + remove unneeded and potentially unsecure include paths.
* debian/patches: selected patches from the upstream SVN repository
  + 40_password.dpatch: skip reading the password file when running as a CGI.
  + 50_ldap.dpatch: Make the 'scope' option in the LDAP probe actually work.
  + 60_fping.dpatch:
    * Support the '-S' (set source address, see #198486) fping option.
    * Don't try to execute fping when running as a CGI.
  + 70_syslog.dpatch: Don't die silently if syslogd is unavailable.
    (Closes: #395056)
* Remove all the autogenerated documentation at clean time, to properly
  undo the effects of the 'build' target.
* Install example configuration files for documentation.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
package Smokeping::probes::CiscoRTTMonDNS;
 
2
 
 
3
=head1 301 Moved Permanently
 
4
 
 
5
This is a Smokeping probe module. Please use the command 
 
6
 
 
7
C<smokeping -man Smokeping::probes::CiscoRTTMonDNS>
 
8
 
 
9
to view the documentation or the command
 
10
 
 
11
C<smokeping -makepod Smokeping::probes::CiscoRTTMonDNS>
 
12
 
 
13
to generate the POD document.
 
14
 
 
15
=cut
 
16
 
 
17
use strict;
 
18
use base qw(Smokeping::probes::basefork);
 
19
use Symbol;
 
20
use Carp;
 
21
use BER;
 
22
use SNMP_Session;
 
23
use SNMP_util "0.97";
 
24
use Smokeping::ciscoRttMonMIB "0.2";
 
25
 
 
26
my $e = "=";
 
27
sub pod_hash {
 
28
        return {
 
29
                name => <<DOC,
 
30
Smokeping::probes::CiscoRTTMonDNS.pm - Probe for SmokePing
 
31
DOC
 
32
                description => <<DOC,
 
33
A probe for smokeping, which uses the ciscoRttMon MIB functionality ("Service Assurance Agent", "SAA") of Cisco IOS to time ( recursive, type A) DNS queries to a DNS server.
 
34
 
 
35
DOC
 
36
 
 
37
                notes => <<DOC,
 
38
${e}head2 host parameter
 
39
 
 
40
The host parameter specifies the DNS server, which the router will use.
 
41
 
 
42
${e}head2 IOS VERSIONS
 
43
 
 
44
This probe only works with IOS 12.0(3)T or higher.  It is recommended to test it on less critical routers first. 
 
45
 
 
46
${e}head2 INSTALLATION
 
47
 
 
48
To install this probe copy ciscoRttMonMIB.pm to (\$SMOKEPINGINSTALLDIR)/lib/Smokeping and CiscoRTTMonDNS.pm to (\$SMOKEPINGINSTALLDIR)/lib/Smokeping/probes.
 
49
 
 
50
The router(s) must be configured to allow read/write SNMP access. Sufficient is:
 
51
 
 
52
        snmp-server community RTTCommunity RW
 
53
 
 
54
If you want to be a bit more restrictive with SNMP write access to the router, then consider configuring something like this 
 
55
 
 
56
        access-list 2 permit 10.37.3.5
 
57
        snmp-server view RttMon ciscoRttMonMIB included
 
58
        snmp-server community RTTCommunity view RttMon RW 2
 
59
 
 
60
The above configuration grants SNMP read-write only to 10.37.3.5 (the smokeping host) and only to the ciscoRttMon MIB tree. The probe does not need access to SNMP variables outside the RttMon tree.
 
61
DOC
 
62
                bugs => <<DOC,
 
63
The probe does unnecessary DNS queries, i.e. more than configured in the "pings" variable, because the RTTMon MIB only allows to set a total time for all queries in one measurement run (one "life"). Currently the probe sets the life duration to "pings"*2+3 seconds (2 secs is the timeout value hardcoded into this probe). 
 
64
DOC
 
65
                see_also => <<DOC,
 
66
L<http://oss.oetiker.ch/smokeping/>
 
67
 
 
68
L<http://www.switch.ch/misc/leinen/snmp/perl/>
 
69
 
 
70
The best source for background info on SAA is Cisco's documentation on L<http://www.cisco.com> and the CISCO-RTTMON-MIB documentation, which is available at: 
 
71
 
 
72
L<ftp://ftp.cisco.com/pub/mibs/v2/CISCO-RTTMON-MIB.my>
 
73
DOC
 
74
                authors => <<DOC,
 
75
Joerg.Kummer at Roche.com 
 
76
DOC
 
77
        }
 
78
}
 
79
 
 
80
my $pingtimeout =2;
 
81
 
 
82
sub new($$$)
 
83
{
 
84
    my $proto = shift;
 
85
    my $class = ref($proto) || $proto;
 
86
    my $self = $class->SUPER::new(@_);
 
87
 
 
88
    # no need for this if we run as a cgi
 
89
    unless ( $ENV{SERVER_SOFTWARE} ) {
 
90
        $self->{pingfactor} = 1000;
 
91
    };
 
92
    return $self;
 
93
}
 
94
 
 
95
sub ProbeDesc($){
 
96
    my $self = shift;
 
97
    return "CiscoRTTMonDNS.pm";
 
98
}
 
99
 
 
100
sub pingone ($$) { 
 
101
    my $self = shift;
 
102
    my $target = shift;
 
103
 
 
104
    my $name = $target->{vars}{name};
 
105
    
 
106
    my $pings = $self->pings($target) || 20;
 
107
 
 
108
    # use the proces ID as as row number to make this poll distinct on the router; 
 
109
    my $row=$$;
 
110
 
 
111
    if (defined 
 
112
        StartRttMibEcho($target->{vars}{ioshost}.":::::2", $target->{addr}, $name,
 
113
        $pings, $target->{vars}{iosint}, $row)) 
 
114
        {
 
115
        # wait for the series to finish
 
116
        sleep ($pings*$pingtimeout+5);
 
117
        if (my @times=FillTimesFromHistoryTable($target->{vars}{ioshost}.":::::2", $pings, $row)){
 
118
                DestroyData ($target->{vars}{ioshost}.":::::2", $row);
 
119
                return @times;
 
120
           }
 
121
        else {
 
122
                return();
 
123
                }
 
124
        }
 
125
    else {
 
126
        return ();
 
127
    } 
 
128
}
 
129
 
 
130
sub StartRttMibEcho ($$$$$$){
 
131
        my ($host, $target, $dnsName, $pings, $sourceip, $row) = @_;
 
132
 
 
133
        # resolve the target name and encode its IP address
 
134
        $_=$target;
 
135
        if (!/^([0-9]|\.)+/) {
 
136
                (my $name, my $aliases, my $addrtype, my $length, my @addrs) = gethostbyname ($target);
 
137
                $target=join('.',(unpack("C4",$addrs[0])));
 
138
                }
 
139
        my @octets=split(/\./,$target);
 
140
        my $encoded_target= pack ("CCCC", @octets);
 
141
 
 
142
        # resolve the source name and encode its IP address
 
143
        my $encoded_source = undef;
 
144
        if (defined $sourceip) {
 
145
                $_=$sourceip;
 
146
                if (!/^([0-9]|\.)+/) {
 
147
                        (my $name, my $aliases, my $addrtype, my $length, my @addrs) = gethostbyname ($sourceip);
 
148
                        $sourceip=join('.',(unpack("C4",$addrs[0])));
 
149
                        }
 
150
                my @octets=split(/\./,$sourceip);
 
151
                $encoded_source= pack ("CCCC", @octets);
 
152
                }
 
153
 
 
154
        #############################################################
 
155
        # rttMonCtrlAdminStatus - 1:active 2:notInService 3:notReady 4:createAndGo 5:createAndWait 6:destroy
 
156
        #delete data from former measurements
 
157
        #return undef unless defined 
 
158
        #  &snmpset($host, "rttMonCtrlAdminStatus.$row",'integer',      6);
 
159
 
 
160
        ############################################################# 
 
161
        # Check RTTMon version and supported protocols
 
162
        $SNMP_Session::suppress_warnings = 10; # be silent
 
163
        (my $version)=&snmpget ($host, "rttMonApplVersion");
 
164
        if (! defined $version ) {
 
165
                Smokeping::do_log ("$host doesn't support or allow RTTMon !\n");
 
166
                return undef;
 
167
        }
 
168
        Smokeping::do_log ("$host supports $version\n");
 
169
        $SNMP_Session::suppress_warnings = 0; # report errors
 
170
 
 
171
        # echo(1), pathEcho(2), fileIO(3), script(4), udpEcho(5), tcpConnect(6), http(7), 
 
172
        # dns(8), jitter(9), dlsw(10), dhcp(11), ftp(12)
 
173
 
 
174
        my $DnsSupported=0==1;
 
175
        snmpmaptable ($host,
 
176
                sub () {
 
177
                        my ($proto, $supported) = @_;
 
178
                        # 1 is true , 2 is false
 
179
                        $DnsSupported=0==0 if ($proto==8 && $supported==1);
 
180
                },
 
181
                "rttMonApplSupportedRttTypesValid");
 
182
 
 
183
        if (! $DnsSupported) {
 
184
                Smokeping::do_log ("$host doesn't support DNS resolution time measurements !\n");
 
185
                return undef;
 
186
        }
 
187
 
 
188
 
 
189
        #############################################################
 
190
        #setup the new data row
 
191
 
 
192
        my @params=();
 
193
        push @params,  
 
194
                "rttMonCtrlAdminStatus.$row",           'integer',      5,
 
195
                "rttMonCtrlAdminRttType.$row",          'integer',      8,
 
196
                "rttMonEchoAdminProtocol.$row",         'integer',      26,
 
197
                "rttMonEchoAdminNameServer.$row",       'octetstring',  $encoded_target,
 
198
                "rttMonEchoAdminTargetAddressString.$row",'octetstring', $dnsName,
 
199
                "rttMonCtrlAdminTimeout.$row",          'integer',      $pingtimeout*1000,
 
200
                "rttMonCtrlAdminFrequency.$row",        'integer',      $pingtimeout,
 
201
                "rttMonCtrlAdminNvgen.$row",            'integer',      2,
 
202
                "rttMonHistoryAdminNumBuckets.$row",    'integer',      $pings,
 
203
                "rttMonHistoryAdminNumLives.$row",      'integer',      1,
 
204
                "rttMonHistoryAdminFilter.$row",        'integer',      2,
 
205
                "rttMonScheduleAdminRttStartTime.$row", 'timeticks',    1,
 
206
                "rttMonScheduleAdminRttLife.$row",      'integer',      $pings*$pingtimeout+3,
 
207
                "rttMonScheduleAdminConceptRowAgeout.$row",'integer',   60;
 
208
 
 
209
                # the router (or this script) doesn't check whether the IP address is one of 
 
210
                # the router's IP address, i.e. the router might send packets, but never 
 
211
                # gets replies..
 
212
                if (defined $sourceip) {
 
213
                        push @params,   "rttMonEchoAdminSourceAddress.$row",            'octetstring',  $encoded_source;
 
214
                }
 
215
 
 
216
        return undef unless defined 
 
217
           &snmpset($host, @params);
 
218
 
 
219
        #############################################################
 
220
        # and go !
 
221
        return undef unless defined 
 
222
           &snmpset($host, "rttMonCtrlAdminStatus.$row",'integer',1);
 
223
 
 
224
        return 1;
 
225
}
 
226
 
 
227
 
 
228
# RttResponseSense values
 
229
# 1:ok 2:disconnected 3:overThreshold 4:timeout 5:busy 6:notConnected 7:dropped 8:sequenceError 
 
230
# 9:verifyError 10:applicationSpecific 11:dnsServerTimeout 12:tcpConnectTimeout 13:httpTransactionTimeout
 
231
#14:dnsQueryError 15:httpError 16:error
 
232
 
 
233
sub FillTimesFromHistoryTable($$$$) {
 
234
        my ($host, $pings, $row) = @_;
 
235
        my @times;
 
236
 
 
237
        # snmpmaptable walks two tables (of equal size)
 
238
        # - "rttMonHistoryCollectionCompletionTime.$row", 
 
239
        # - "rttMonHistoryCollectionSense.$row"
 
240
        # The code in the sub() argument is executed for each index value snmptable walks
 
241
 
 
242
        snmpmaptable ($host, 
 
243
                sub () {
 
244
                        my ($index, $rtt, $status) = @_;
 
245
                        push @times, (sprintf ("%.10e", $rtt/1000))
 
246
                                if ($status==1);
 
247
                        },
 
248
                "rttMonHistoryCollectionCompletionTime.$row",
 
249
                "rttMonHistoryCollectionSense.$row");
 
250
 
 
251
        return sort { $a <=> $b } @times;
 
252
}
 
253
 
 
254
sub DestroyData ($$) {
 
255
        my ($host, $row) = @_;
 
256
 
 
257
        &snmpset($host, "rttMonCtrlOperState.$row",             'integer',      3);
 
258
        &snmpset($host, "rttMonCtrlAdminStatus.$row",           'integer',      2);
 
259
        #delete any old config
 
260
        &snmpset($host, "rttMonCtrlAdminStatus.$row",           'integer',      6);
 
261
}
 
262
 
 
263
sub targetvars {
 
264
        my $class = shift;
 
265
        return $class->_makevars($class->SUPER::targetvars, {
 
266
                _mandatory => [ 'ioshost', 'name' ],
 
267
                ioshost => {
 
268
                        _doc => <<DOC,
 
269
The (mandatory) ioshost parameter specifies the Cisco router, which will send the DNS requests, 
 
270
as well as the SNMP community string on the router.
 
271
DOC
 
272
                        _example => 'RTTcommunity@Myrouter.foobar.com.au',
 
273
                },
 
274
                name => {
 
275
                        _doc => "The (mandatory) name parameter is the DNS name to resolve.",
 
276
                        _example => 'www.foobar.com.au',
 
277
                },
 
278
                iosint => {
 
279
                        _doc => <<DOC,
 
280
The (optional) iosint parameter is the source address for the DNS packets.
 
281
This should be one of the active (!) IP addresses of the router to get
 
282
results. IOS looks up the target host address in the forwarding table
 
283
and then uses the interface(s) listed there to send the DNS packets. By
 
284
default IOS uses the (primary) IP address on the sending interface as
 
285
source address for packets originated by the router.
 
286
DOC
 
287
                        _example => '10.33.22.11',
 
288
                },
 
289
        });
 
290
}
 
291
 
 
292
=head1 
 
293
1;
 
294