diff options
Diffstat (limited to 'web/attachments/302952-check_ifstatus')
-rw-r--r-- | web/attachments/302952-check_ifstatus | 483 |
1 files changed, 483 insertions, 0 deletions
diff --git a/web/attachments/302952-check_ifstatus b/web/attachments/302952-check_ifstatus new file mode 100644 index 0000000..2381fd2 --- /dev/null +++ b/web/attachments/302952-check_ifstatus | |||
@@ -0,0 +1,483 @@ | |||
1 | #! /opt/coolstack/bin/perl -w | ||
2 | # vim:foldmethod=syntax:tabstop=4:shiftwidth=4 | ||
3 | # | ||
4 | # Matthew Martin, Tuesday August 14, 2007 | ||
5 | # Problems with check_ifstatus.pl | ||
6 | # 1) "No response from remote host" should be unknown, not critical, right? | ||
7 | # 2) Serial link "dormant" should be critical, not okay | ||
8 | # 3) dormant, excluded and unused interfaces are not correctly counted | ||
9 | # 4) add some default exclusions | ||
10 | # | ||
11 | # check_ifstatus.pl - nagios plugin | ||
12 | # | ||
13 | # | ||
14 | # Copyright (C) 2000 Christoph Kron | ||
15 | # Modified 5/2002 to conform to updated Nagios Plugin Guidelines (S. Ghosh) | ||
16 | # Added -x option (4/2003) | ||
17 | # Added -u option (4/2003) | ||
18 | # Added -M option (10/2003) | ||
19 | # Added SNMPv3 support (10/2003) | ||
20 | # | ||
21 | # This program is free software; you can redistribute it and/or | ||
22 | # modify it under the terms of the GNU General Public License | ||
23 | # as published by the Free Software Foundation; either version 2 | ||
24 | # of the License, or (at your option) any later version. | ||
25 | # | ||
26 | # This program is distributed in the hope that it will be useful, | ||
27 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
28 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
29 | # GNU General Public License for more details. | ||
30 | # | ||
31 | # You should have received a copy of the GNU General Public License | ||
32 | # along with this program; if not, write to the Free Software | ||
33 | # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
34 | # | ||
35 | # | ||
36 | # Report bugs to: ck@zet.net, nagiosplug-help@lists.sf.net | ||
37 | # | ||
38 | # 11.01.2000 Version 1.0 | ||
39 | # | ||
40 | # $Id: check_ifstatus.pl 884 2004-08-18 19:51:35Z tonvoon $ | ||
41 | |||
42 | use POSIX; | ||
43 | use strict; | ||
44 | use lib "/opt/nagios-3.0.5/libexec" ; | ||
45 | use utils qw($TIMEOUT %ERRORS &print_revision &support); | ||
46 | |||
47 | use Net::SNMP; | ||
48 | use Getopt::Long; | ||
49 | Getopt::Long::Configure('bundling'); | ||
50 | |||
51 | my $PROGNAME = "check_ifstatus"; | ||
52 | |||
53 | sub print_help (); | ||
54 | sub usage (); | ||
55 | sub process_arguments (); | ||
56 | |||
57 | |||
58 | my $status; | ||
59 | my %ifOperStatus = ('1','up', | ||
60 | '2','down', | ||
61 | '3','testing', | ||
62 | '4','unknown', | ||
63 | '5','dormant', | ||
64 | '6','notPresent', | ||
65 | '7','lowerLayerDown'); # down due to the state of lower layer interface(s)); | ||
66 | |||
67 | my $timeout ; | ||
68 | my $state = "UNKNOWN"; | ||
69 | my $answer = ""; | ||
70 | my $snmpkey=0; | ||
71 | my $snmpoid=0; | ||
72 | my $key=0; | ||
73 | my $community = "public"; | ||
74 | my $maxmsgsize = 1472 ; # Net::SNMP default is 1472 | ||
75 | my ($seclevel, $authproto, $secname, $authpass, $privpass, $auth, $priv, $context); | ||
76 | my $port = 161; | ||
77 | my @snmpoids; | ||
78 | my $snmpIfAdminStatus = '1.3.6.1.2.1.2.2.1.7'; | ||
79 | my $snmpIfDescr = '1.3.6.1.2.1.2.2.1.2'; | ||
80 | my $snmpIfOperStatus = '1.3.6.1.2.1.2.2.1.8'; | ||
81 | my $snmpIfName = '1.3.6.1.2.1.31.1.1.1.1'; | ||
82 | my $snmpIfAlias = '1.3.6.1.2.1.31.1.1.1.18'; | ||
83 | my $snmpLocIfDescr = '1.3.6.1.4.1.9.2.2.1.1.28'; | ||
84 | my $snmpIfType = '1.3.6.1.2.1.2.2.1.3'; | ||
85 | my $hostname; | ||
86 | my $session; | ||
87 | my $error; | ||
88 | my $response; | ||
89 | my %ifStatus; | ||
90 | my $ifup =0 ; | ||
91 | my $ifdown =0; | ||
92 | my $ifdormant = 0; | ||
93 | my $ifexclude = 0 ; | ||
94 | my $ifunused = 0; | ||
95 | my $ifmessage = ""; | ||
96 | my $snmp_version = 1; | ||
97 | my $ifXTable; | ||
98 | my $opt_h ; | ||
99 | my $opt_V ; | ||
100 | my $opt_u; | ||
101 | my $opt_x ; | ||
102 | my %excluded ; | ||
103 | my @unused_ports ; | ||
104 | |||
105 | # Just in case of problems, let's not hang Nagios | ||
106 | $SIG{'ALRM'} = sub { | ||
107 | print ("ERROR: No snmp response from $hostname (alarm timeout)\n"); | ||
108 | exit $ERRORS{"UNKNOWN"}; | ||
109 | }; | ||
110 | |||
111 | |||
112 | #Option checking | ||
113 | $status = process_arguments(); | ||
114 | |||
115 | if ($status != 0) | ||
116 | { | ||
117 | print_help() ; | ||
118 | exit $ERRORS{'OK'}; | ||
119 | } | ||
120 | |||
121 | |||
122 | alarm($timeout); | ||
123 | |||
124 | push(@snmpoids,$snmpIfOperStatus); | ||
125 | push(@snmpoids,$snmpIfAdminStatus); | ||
126 | push(@snmpoids,$snmpIfDescr); | ||
127 | push(@snmpoids,$snmpIfType); | ||
128 | push(@snmpoids,$snmpIfName) if ( defined $ifXTable); | ||
129 | push(@snmpoids,$snmpIfAlias) if ( defined $ifXTable); | ||
130 | |||
131 | |||
132 | |||
133 | |||
134 | foreach $snmpoid (@snmpoids) { | ||
135 | |||
136 | if (!defined($response = $session->get_table($snmpoid))) { | ||
137 | $answer=$session->error; | ||
138 | $session->close; | ||
139 | # mgmart6. Tuesday August 14, 2007 | ||
140 | # I think a SNMP error should give UNKNOWN, not CRITICAL | ||
141 | #$state = 'CRITICAL'; | ||
142 | $state = 'UNKNOWN'; | ||
143 | if ( ( $snmpoid =~ $snmpIfName ) && defined $ifXTable ) { | ||
144 | print ("$state: Device does not support ifTable - try without -I option\n"); | ||
145 | }else{ | ||
146 | print ("$state: $answer for $snmpoid with snmp version $snmp_version\n"); | ||
147 | } | ||
148 | exit $ERRORS{$state}; | ||
149 | } | ||
150 | |||
151 | foreach $snmpkey (keys %{$response}) { | ||
152 | $snmpkey =~ /.*\.(\d+)$/; | ||
153 | $key = $1; | ||
154 | $ifStatus{$key}{$snmpoid} = $response->{$snmpkey}; | ||
155 | } | ||
156 | } | ||
157 | |||
158 | |||
159 | $session->close; | ||
160 | |||
161 | alarm(0); | ||
162 | |||
163 | # mgmart6. This script cannot tell that specific logical interfaces are | ||
164 | # associated with their phys IF so it checks them all. | ||
165 | foreach $key (keys %ifStatus) { | ||
166 | |||
167 | # Skip interfaces flagged with -u (--unused_ports) | ||
168 | # "A comma separated list of ifIndex values that should be excluded" | ||
169 | if (!defined($ifStatus{$key}{'notInUse'})) { | ||
170 | # check only if interface is administratively up | ||
171 | if ($ifStatus{$key}{$snmpIfAdminStatus} == 1 ) { | ||
172 | |||
173 | # check only if interface type is not listed in %excluded | ||
174 | if (!defined $excluded{$ifStatus{$key}{$snmpIfType}} ) { | ||
175 | if ($ifStatus{$key}{$snmpIfOperStatus} == 1 ) { $ifup++ ;} | ||
176 | if ($ifStatus{$key}{$snmpIfOperStatus} == 2 ) { | ||
177 | $ifdown++ ; | ||
178 | if (defined $ifXTable) { | ||
179 | $ifmessage .= sprintf("%s: down -> %s<BR>", | ||
180 | $ifStatus{$key}{$snmpIfName}, | ||
181 | $ifStatus{$key}{$snmpIfAlias}); | ||
182 | }else{ | ||
183 | $ifmessage .= sprintf("%s: down <BR>", | ||
184 | $ifStatus{$key}{$snmpIfDescr}); | ||
185 | } | ||
186 | } | ||
187 | if ($ifStatus{$key}{$snmpIfOperStatus} == 5 ) { $ifdormant++ ;} | ||
188 | # Matthew Martin Interface is listed in %excluded | ||
189 | } else { | ||
190 | $ifexclude++; | ||
191 | } | ||
192 | # mgmart6 If not administratively up, mark as unused. | ||
193 | } elsif ($ifStatus{$key}{$snmpIfAdminStatus} == 2 ) { | ||
194 | $ifunused++; | ||
195 | } | ||
196 | }else{ | ||
197 | # mgmart6. Original line: $ifunused++; | ||
198 | # actually matches the flag | ||
199 | # -u (--unused_ports) A comma separated list of ifIndex values that should be excluded | ||
200 | # They should be marked as excluded, not unused. | ||
201 | $ifexclude++; | ||
202 | } | ||
203 | } | ||
204 | |||
205 | # mgmart6 | ||
206 | # The original has dormant serial interfaces return status of "OK". | ||
207 | # A dormant serial connection should be CRITICAL, right? | ||
208 | # I changed the following line to address this: | ||
209 | #if ($ifdown > 0) { | ||
210 | if (($ifdown > 0) || ($ifdormant > 0)) { | ||
211 | $state = 'CRITICAL'; | ||
212 | $answer = sprintf("host '%s', interfaces up: %d, down: %d, dormant: %d, excluded: %d, unused: %d<BR>", | ||
213 | $hostname, | ||
214 | $ifup, | ||
215 | $ifdown, | ||
216 | $ifdormant, | ||
217 | $ifexclude, | ||
218 | $ifunused); | ||
219 | $answer = $answer . $ifmessage . "\n"; | ||
220 | } else { | ||
221 | $state = 'OK'; | ||
222 | $answer = sprintf("host '%s', interfaces up: %d, down: %d, dormant: %d, excluded: %d, unused: %d", | ||
223 | $hostname, | ||
224 | $ifup, | ||
225 | $ifdown, | ||
226 | $ifdormant, | ||
227 | $ifexclude, | ||
228 | $ifunused); | ||
229 | } | ||
230 | my $perfdata = sprintf("up=%d,down=%d,dormant=%d,excluded=%d,unused=%d",$ifup,$ifdown,$ifdormant,$ifexclude,$ifunused); | ||
231 | print ("$state: $answer |$perfdata\n"); | ||
232 | exit $ERRORS{$state}; | ||
233 | |||
234 | |||
235 | sub usage (){ | ||
236 | printf "\nMissing arguments!\n"; | ||
237 | printf "\n"; | ||
238 | printf "check_ifstatus -C <READCOMMUNITY> -p <PORT> -H <HOSTNAME>\n"; | ||
239 | printf "Copyright (C) 2000 Christoph Kron\n"; | ||
240 | printf "Updates 5/2002 Subhendu Ghosh\n"; | ||
241 | printf "\n\n"; | ||
242 | support(); | ||
243 | exit $ERRORS{"UNKNOWN"}; | ||
244 | } | ||
245 | |||
246 | sub print_help (){ | ||
247 | printf "check_ifstatus plugin for Nagios monitors operational \n"; | ||
248 | printf "status of each network interface on the target host\n"; | ||
249 | printf "\nUsage:\n"; | ||
250 | printf " -H (--hostname) Hostname to query - (required)\n"; | ||
251 | printf " -C (--community) SNMP read community (defaults to public,\n"; | ||
252 | printf " used with SNMP v1 and v2c\n"; | ||
253 | printf " -v (--snmp_version) 1 for SNMP v1 (default)\n"; | ||
254 | printf " 2 for SNMP v2c\n"; | ||
255 | printf " SNMP v2c will use get_bulk for less overhead\n"; | ||
256 | printf " 3 for SNMPv3 (requires -U option)"; | ||
257 | printf " -p (--port) SNMP port (default 161)\n"; | ||
258 | printf " -I (--ifmib) Agent supports IFMIB ifXTable. For Cisco - this will provide\n"; | ||
259 | printf " the descriptive name. Do not use if you don't know what this is. \n"; | ||
260 | printf " -x (--exclude) A comma separated list of ifType values that should be excluded \n"; | ||
261 | printf " from the report (default for an empty list is PPP(23).\n"; | ||
262 | printf " -u (--unused_ports) A comma separated list of ifIndex values that should be excluded \n"; | ||
263 | printf " from the report (default is an empty exclusion list).\n"; | ||
264 | printf " See the IANAifType-MIB for a list of interface types.\n"; | ||
265 | printf " -L (--seclevel) choice of \"noAuthNoPriv\", \"authNoPriv\", or \"authPriv\"\n"; | ||
266 | printf " -U (--secname) username for SNMPv3 context\n"; | ||
267 | printf " -c (--context) SNMPv3 context name (default is empty string)"; | ||
268 | printf " -A (--authpass) authentication password (cleartext ascii or localized key\n"; | ||
269 | printf " in hex with 0x prefix generated by using \"snmpkey\" utility\n"; | ||
270 | printf " auth password and authEngineID\n"; | ||
271 | printf " -a (--authproto) Authentication protocol ( MD5 or SHA1)\n"; | ||
272 | printf " -X (--privpass) privacy password (cleartext ascii or localized key\n"; | ||
273 | printf " in hex with 0x prefix generated by using \"snmpkey\" utility\n"; | ||
274 | printf " privacy password and authEngineID\n"; | ||
275 | printf " -M (--maxmsgsize) Max message size - usefull only for v1 or v2c\n"; | ||
276 | printf " -t (--timeout) seconds before the plugin times out (default=$TIMEOUT)\n"; | ||
277 | printf " -V (--version) Plugin version\n"; | ||
278 | printf " -h (--help) usage help \n\n"; | ||
279 | print_revision($PROGNAME, '$Revision: 884 $'); | ||
280 | |||
281 | } | ||
282 | |||
283 | sub process_arguments() { | ||
284 | $status = GetOptions( | ||
285 | "V" => \$opt_V, "version" => \$opt_V, | ||
286 | "h" => \$opt_h, "help" => \$opt_h, | ||
287 | "v=i" => \$snmp_version, "snmp_version=i" => \$snmp_version, | ||
288 | "C=s" => \$community,"community=s" => \$community, | ||
289 | "L=s" => \$seclevel, "seclevel=s" => \$seclevel, | ||
290 | "a=s" => \$authproto, "authproto=s" => \$authproto, | ||
291 | "U=s" => \$secname, "secname=s" => \$secname, | ||
292 | "A=s" => \$authpass, "authpass=s" => \$authpass, | ||
293 | "X=s" => \$privpass, "privpass=s" => \$privpass, | ||
294 | "c=s" => \$context, "context=s" => \$context, | ||
295 | "p=i" =>\$port, "port=i" => \$port, | ||
296 | "H=s" => \$hostname, "hostname=s" => \$hostname, | ||
297 | "I" => \$ifXTable, "ifmib" => \$ifXTable, | ||
298 | "x:s" => \$opt_x, "exclude:s" => \$opt_x, | ||
299 | "u=s" => \$opt_u, "unused_ports=s" => \$opt_u, | ||
300 | "M=i" => \$maxmsgsize, "maxmsgsize=i" => \$maxmsgsize, | ||
301 | "t=i" => \$timeout, "timeout=i" => \$timeout, | ||
302 | ); | ||
303 | |||
304 | if ($status == 0){ | ||
305 | print_help() ; | ||
306 | exit $ERRORS{'OK'}; | ||
307 | } | ||
308 | if ($opt_V) { | ||
309 | print_revision($PROGNAME,'$Revision: 884 $ '); | ||
310 | exit $ERRORS{'OK'}; | ||
311 | } | ||
312 | |||
313 | if ($opt_h) { | ||
314 | print_help(); | ||
315 | exit $ERRORS{'OK'}; | ||
316 | } | ||
317 | |||
318 | unless (defined $timeout) { | ||
319 | $timeout = $TIMEOUT; | ||
320 | } | ||
321 | |||
322 | if ($snmp_version =~ /3/ ) { | ||
323 | # Must define a security level even though default is noAuthNoPriv | ||
324 | # v3 requires a security username | ||
325 | if (defined $seclevel && defined $secname) { | ||
326 | |||
327 | # Must define a security level even though defualt is noAuthNoPriv | ||
328 | unless ($seclevel eq ('noAuthNoPriv' || 'authNoPriv' || 'authPriv' ) ) { | ||
329 | usage(); | ||
330 | exit $ERRORS{"UNKNOWN"}; | ||
331 | } | ||
332 | |||
333 | # Authentication wanted | ||
334 | if ($seclevel eq ('authNoPriv' || 'authPriv') ) { | ||
335 | |||
336 | unless ($authproto eq ('MD5' || 'SHA1') ) { | ||
337 | usage(); | ||
338 | exit $ERRORS{"UNKNOWN"}; | ||
339 | } | ||
340 | |||
341 | if ( !defined $authpass) { | ||
342 | usage(); | ||
343 | exit $ERRORS{"UNKNOWN"}; | ||
344 | }else{ | ||
345 | if ($authpass =~ /^0x/ ) { | ||
346 | $auth = "-authkey => $authpass" ; | ||
347 | }else{ | ||
348 | $auth = "-authpassword => $authpass"; | ||
349 | } | ||
350 | } | ||
351 | |||
352 | } | ||
353 | |||
354 | # Privacy (DES encryption) wanted | ||
355 | if ($seclevel eq 'authPriv' ) { | ||
356 | if (! defined $privpass) { | ||
357 | usage(); | ||
358 | exit $ERRORS{"UNKNOWN"}; | ||
359 | }else{ | ||
360 | if ($privpass =~ /^0x/){ | ||
361 | $priv = "-privkey => $privpass"; | ||
362 | }else{ | ||
363 | $priv = "-privpassword => $privpass"; | ||
364 | } | ||
365 | } | ||
366 | } | ||
367 | |||
368 | # Context name defined or default | ||
369 | |||
370 | unless ( defined $context) { | ||
371 | $context = ""; | ||
372 | } | ||
373 | |||
374 | |||
375 | |||
376 | }else { | ||
377 | usage(); | ||
378 | exit $ERRORS{'UNKNOWN'}; ; | ||
379 | } | ||
380 | } # end snmpv3 | ||
381 | |||
382 | # for snmp v1 & v2c we default to community = "public" | ||
383 | |||
384 | # Excluded interfaces types (ifType) (backup interfaces, dial-on demand interfaces, PPP interfaces | ||
385 | if (defined $opt_x) { | ||
386 | my @x = split(/,/, $opt_x); | ||
387 | if ( @x) { | ||
388 | foreach $key (@x){ | ||
389 | $excluded{$key} = 1; | ||
390 | } | ||
391 | } | ||
392 | # Matthew Martin In the original this else was nested wrong and never matched | ||
393 | } else { | ||
394 | $excluded{23} = 1; # default PPP(23) if empty list - note (AIX seems to think PPP is 22 according to a post) | ||
395 | $excluded{24} = 1; # mgmart6, Tuesday August 14, 2007, Nokia, ifDescr.6 = loop0c0 Software Loopback Layer -- ifType.6 = softwareLoopback(24) (taken from a Nokia IP330) | ||
396 | $excluded{25} = 1; # mgmart6, Tuesday August 14, 2007, Nokia, ifDescr.1 = pppoe0 Ethernet Layer -- ifType.1 = eon(25) (from a Nokia IP350) | ||
397 | } | ||
398 | |||
399 | # Excluded interface ports (ifIndex) - management reasons | ||
400 | if ($opt_u) { | ||
401 | @unused_ports = split(/,/,$opt_u); | ||
402 | foreach $key (@unused_ports) { | ||
403 | $ifStatus{$key}{'notInUse'}++ ; | ||
404 | } | ||
405 | } | ||
406 | |||
407 | if (! utils::is_hostname($hostname)){ | ||
408 | usage(); | ||
409 | exit $ERRORS{"UNKNOWN"}; | ||
410 | } | ||
411 | |||
412 | # create SNMP session handle based on options passed. | ||
413 | |||
414 | if ( ! $snmp_version ) { | ||
415 | $snmp_version =1 ; | ||
416 | }else{ | ||
417 | if ( $snmp_version =~ /[12]/ ) { | ||
418 | |||
419 | ($session, $error) = Net::SNMP->session( | ||
420 | -hostname => $hostname, | ||
421 | -community => $community, | ||
422 | -port => $port, | ||
423 | -version => $snmp_version, | ||
424 | -maxmsgsize => $maxmsgsize | ||
425 | ); | ||
426 | |||
427 | if (!defined($session)) { | ||
428 | $state='UNKNOWN'; | ||
429 | $answer=$error; | ||
430 | print ("$state: $answer"); | ||
431 | exit $ERRORS{$state}; | ||
432 | } | ||
433 | |||
434 | |||
435 | }elsif ( $snmp_version =~ /3/ ) { | ||
436 | |||
437 | if ($seclevel eq 'noAuthNoPriv') { | ||
438 | ($session, $error) = Net::SNMP->session( | ||
439 | -hostname => $hostname, | ||
440 | -port => $port, | ||
441 | -version => $snmp_version, | ||
442 | -username => $secname, | ||
443 | ); | ||
444 | |||
445 | }elsif ( $seclevel eq 'authNoPriv' ) { | ||
446 | ($session, $error) = Net::SNMP->session( | ||
447 | -hostname => $hostname, | ||
448 | -port => $port, | ||
449 | -version => $snmp_version, | ||
450 | -username => $secname, | ||
451 | -authprotocol => $authproto, | ||
452 | $auth | ||
453 | ); | ||
454 | }elsif ($seclevel eq 'authPriv' ) { | ||
455 | ($session, $error) = Net::SNMP->session( | ||
456 | -hostname => $hostname, | ||
457 | -port => $port, | ||
458 | -version => $snmp_version, | ||
459 | -username => $secname, | ||
460 | -authprotocol => $authproto, | ||
461 | $auth, | ||
462 | $priv | ||
463 | ); | ||
464 | } | ||
465 | |||
466 | |||
467 | if (!defined($session)) { | ||
468 | $state='UNKNOWN'; | ||
469 | $answer=$error; | ||
470 | print ("$state: $answer"); | ||
471 | exit $ERRORS{$state}; | ||
472 | } | ||
473 | |||
474 | }else{ | ||
475 | $state='UNKNOWN'; | ||
476 | print ("$state: No support for SNMP v$snmp_version yet\n"); | ||
477 | exit $ERRORS{$state}; | ||
478 | } | ||
479 | } | ||
480 | |||
481 | return $ERRORS{"OK"}; | ||
482 | |||
483 | } | ||