diff options
author | Matthias Eble <psychotrahe@gmx.de> | 2009-06-11 15:20:55 (GMT) |
---|---|---|
committer | Matthias Eble <psychotrahe@gmx.de> | 2009-06-11 15:20:55 (GMT) |
commit | edda2536e589810070abcb59e3cb2b3d0b334a01 (patch) | |
tree | c65405f5ce165c2a1d0c87c7f826440990353705 | |
parent | e16b35b2ca960f8e56c17013a749e181d429a725 (diff) | |
download | monitoring-plugins-edda2536e589810070abcb59e3cb2b3d0b334a01.tar.gz |
Fixed SNMPv3 behaviour of check_ifstatus. Added -P to define privprotocol (#2343438 - Robin Schroeder)
check_ifstatus didn't function correctly with SNMPv3. This is fixed now.
Created argument-hash for SNMP session creation. This removes redundant code.
Session creation was moved out of process_arguments() and now takes place
after setting the timeout handler.
Additionally the -P argument was added to specify the privprotocol.
-rw-r--r-- | NEWS | 4 | ||||
-rwxr-xr-x | plugins-scripts/check_ifstatus.pl | 170 | ||||
-rw-r--r-- | plugins-scripts/t/check_ifstatus.t | 63 |
3 files changed, 132 insertions, 105 deletions
@@ -39,8 +39,8 @@ This file documents the major additions and syntax changes between releases. | |||
39 | Fixed check_by_ssh interpretation of quotes in -C parameter (#1985246, #2268675) | 39 | Fixed check_by_ssh interpretation of quotes in -C parameter (#1985246, #2268675) |
40 | check_snmp now supports standard threshold ranges and doubles (floating numbers) in thresholds | 40 | check_snmp now supports standard threshold ranges and doubles (floating numbers) in thresholds |
41 | check_fping now supports passing target timeout and interval to fping (#2347686 - Martin Foster) | 41 | check_fping now supports passing target timeout and interval to fping (#2347686 - Martin Foster) |
42 | Fixed SNMPv3 behaviour of check_ifoperstatus. Added -x to define privprotocol (#2343438 - Robin Schroeder) | 42 | Fixed SNMPv3 behaviour of check_ifoperstatus and check_ifstatus. Added -x/-P to define privprotocol (#2343438 - Robin Schroeder) |
43 | check_ifoperstatus is now more userfriendly in case of missing arguments | 43 | check_ifoperstatus and check_ifstatus are now more user-friendly in case of missing arguments |
44 | 44 | ||
45 | 1.4.13 25th Sept 2008 | 45 | 1.4.13 25th Sept 2008 |
46 | Fix Debian bug #460097: check_http --max-age broken (Hilko Bengen) | 46 | Fix Debian bug #460097: check_http --max-age broken (Hilko Bengen) |
diff --git a/plugins-scripts/check_ifstatus.pl b/plugins-scripts/check_ifstatus.pl index bae3ffa..2263823 100755 --- a/plugins-scripts/check_ifstatus.pl +++ b/plugins-scripts/check_ifstatus.pl | |||
@@ -42,7 +42,8 @@ Getopt::Long::Configure('bundling'); | |||
42 | my $PROGNAME = "check_ifstatus"; | 42 | my $PROGNAME = "check_ifstatus"; |
43 | 43 | ||
44 | sub print_help (); | 44 | sub print_help (); |
45 | sub usage (); | 45 | sub usage ($); |
46 | sub print_usage (); | ||
46 | sub process_arguments (); | 47 | sub process_arguments (); |
47 | 48 | ||
48 | 49 | ||
@@ -63,7 +64,7 @@ my $snmpoid=0; | |||
63 | my $key=0; | 64 | my $key=0; |
64 | my $community = "public"; | 65 | my $community = "public"; |
65 | my $maxmsgsize = 1472 ; # Net::SNMP default is 1472 | 66 | my $maxmsgsize = 1472 ; # Net::SNMP default is 1472 |
66 | my ($seclevel, $authproto, $secname, $authpass, $privpass, $auth, $priv, $context); | 67 | my ($seclevel, $authproto, $secname, $authpass, $privpass, $privproto, $auth, $priv, $context); |
67 | my $port = 161; | 68 | my $port = 161; |
68 | my @snmpoids; | 69 | my @snmpoids; |
69 | my $snmpIfAdminStatus = '1.3.6.1.2.1.2.2.1.7'; | 70 | my $snmpIfAdminStatus = '1.3.6.1.2.1.2.2.1.7'; |
@@ -92,6 +93,7 @@ my $opt_u; | |||
92 | my $opt_x ; | 93 | my $opt_x ; |
93 | my %excluded ; | 94 | my %excluded ; |
94 | my @unused_ports ; | 95 | my @unused_ports ; |
96 | my %session_opts; | ||
95 | 97 | ||
96 | 98 | ||
97 | 99 | ||
@@ -115,6 +117,15 @@ if ($status != 0) | |||
115 | 117 | ||
116 | 118 | ||
117 | alarm($timeout); | 119 | alarm($timeout); |
120 | ($session, $error) = Net::SNMP->session(%session_opts); | ||
121 | |||
122 | if (!defined($session)) { | ||
123 | $state='UNKNOWN'; | ||
124 | $answer=$error; | ||
125 | print ("$state: $answer\n"); | ||
126 | exit $ERRORS{$state}; | ||
127 | } | ||
128 | |||
118 | 129 | ||
119 | push(@snmpoids,$snmpIfOperStatus); | 130 | push(@snmpoids,$snmpIfOperStatus); |
120 | push(@snmpoids,$snmpIfAdminStatus); | 131 | push(@snmpoids,$snmpIfAdminStatus); |
@@ -209,19 +220,25 @@ my $perfdata = sprintf("up=%d,down=%d,dormant=%d,excluded=%d,unused=%d",$ifup,$i | |||
209 | print ("$state: $answer |$perfdata\n"); | 220 | print ("$state: $answer |$perfdata\n"); |
210 | exit $ERRORS{$state}; | 221 | exit $ERRORS{$state}; |
211 | 222 | ||
223 | sub usage($) { | ||
224 | print "$_[0]\n"; | ||
225 | print_usage(); | ||
226 | exit $ERRORS{"UNKNOWN"}; | ||
227 | } | ||
212 | 228 | ||
213 | sub usage (){ | 229 | sub print_usage() { |
214 | printf "\nMissing arguments!\n"; | ||
215 | printf "\n"; | 230 | printf "\n"; |
231 | printf "usage: \n"; | ||
216 | printf "check_ifstatus -C <READCOMMUNITY> -p <PORT> -H <HOSTNAME>\n"; | 232 | printf "check_ifstatus -C <READCOMMUNITY> -p <PORT> -H <HOSTNAME>\n"; |
217 | printf "Copyright (C) 2000 Christoph Kron\n"; | 233 | printf "Copyright (C) 2000 Christoph Kron\n"; |
218 | printf "Updates 5/2002 Subhendu Ghosh\n"; | 234 | printf "Updates 5/2002 Subhendu Ghosh\n"; |
219 | printf "\n\n"; | ||
220 | support(); | 235 | support(); |
221 | exit $ERRORS{"UNKNOWN"}; | 236 | printf "\n\n"; |
222 | } | 237 | } |
223 | 238 | ||
224 | sub print_help (){ | 239 | sub print_help() { |
240 | print_revision($PROGNAME, '@NP_VERSION@'); | ||
241 | print_usage(); | ||
225 | printf "check_ifstatus plugin for Nagios monitors operational \n"; | 242 | printf "check_ifstatus plugin for Nagios monitors operational \n"; |
226 | printf "status of each network interface on the target host\n"; | 243 | printf "status of each network interface on the target host\n"; |
227 | printf "\nUsage:\n"; | 244 | printf "\nUsage:\n"; |
@@ -242,14 +259,15 @@ sub print_help (){ | |||
242 | printf " See the IANAifType-MIB for a list of interface types.\n"; | 259 | printf " See the IANAifType-MIB for a list of interface types.\n"; |
243 | printf " -L (--seclevel) choice of \"noAuthNoPriv\", \"authNoPriv\", or \"authPriv\"\n"; | 260 | printf " -L (--seclevel) choice of \"noAuthNoPriv\", \"authNoPriv\", or \"authPriv\"\n"; |
244 | printf " -U (--secname) username for SNMPv3 context\n"; | 261 | printf " -U (--secname) username for SNMPv3 context\n"; |
245 | printf " -c (--context) SNMPv3 context name (default is empty string)"; | 262 | printf " -c (--context) SNMPv3 context name (default is empty string)\n"; |
246 | printf " -A (--authpass) authentication password (cleartext ascii or localized key\n"; | 263 | printf " -A (--authpass) authentication password (cleartext ascii or localized key\n"; |
247 | printf " in hex with 0x prefix generated by using \"snmpkey\" utility\n"; | 264 | printf " in hex with 0x prefix generated by using \"snmpkey\" utility\n"; |
248 | printf " auth password and authEngineID\n"; | 265 | printf " auth password and authEngineID\n"; |
249 | printf " -a (--authproto) Authentication protocol ( MD5 or SHA1)\n"; | 266 | printf " -a (--authproto) Authentication protocol (MD5 or SHA1)\n"; |
250 | printf " -X (--privpass) privacy password (cleartext ascii or localized key\n"; | 267 | printf " -X (--privpass) privacy password (cleartext ascii or localized key\n"; |
251 | printf " in hex with 0x prefix generated by using \"snmpkey\" utility\n"; | 268 | printf " in hex with 0x prefix generated by using \"snmpkey\" utility\n"; |
252 | printf " privacy password and authEngineID\n"; | 269 | printf " privacy password and authEngineID\n"; |
270 | printf " -P (--privproto) privacy protocol (DES or AES; default: DES)\n"; | ||
253 | printf " -M (--maxmsgsize) Max message size - usefull only for v1 or v2c\n"; | 271 | printf " -M (--maxmsgsize) Max message size - usefull only for v1 or v2c\n"; |
254 | printf " -t (--timeout) seconds before the plugin times out (default=$TIMEOUT)\n"; | 272 | printf " -t (--timeout) seconds before the plugin times out (default=$TIMEOUT)\n"; |
255 | printf " -V (--version) Plugin version\n"; | 273 | printf " -V (--version) Plugin version\n"; |
@@ -269,6 +287,7 @@ sub process_arguments() { | |||
269 | "U=s" => \$secname, "secname=s" => \$secname, | 287 | "U=s" => \$secname, "secname=s" => \$secname, |
270 | "A=s" => \$authpass, "authpass=s" => \$authpass, | 288 | "A=s" => \$authpass, "authpass=s" => \$authpass, |
271 | "X=s" => \$privpass, "privpass=s" => \$privpass, | 289 | "X=s" => \$privpass, "privpass=s" => \$privpass, |
290 | "P=s" => \$privproto, "privproto=s" => \$privproto, | ||
272 | "c=s" => \$context, "context=s" => \$context, | 291 | "c=s" => \$context, "context=s" => \$context, |
273 | "p=i" =>\$port, "port=i" => \$port, | 292 | "p=i" =>\$port, "port=i" => \$port, |
274 | "H=s" => \$hostname, "hostname=s" => \$hostname, | 293 | "H=s" => \$hostname, "hostname=s" => \$hostname, |
@@ -280,9 +299,10 @@ sub process_arguments() { | |||
280 | ); | 299 | ); |
281 | 300 | ||
282 | if ($status == 0){ | 301 | if ($status == 0){ |
283 | print_help() ; | 302 | print_help(); |
284 | exit $ERRORS{'OK'}; | 303 | exit $ERRORS{'OK'}; |
285 | } | 304 | } |
305 | |||
286 | if ($opt_V) { | 306 | if ($opt_V) { |
287 | print_revision($PROGNAME,'@NP_VERSION@'); | 307 | print_revision($PROGNAME,'@NP_VERSION@'); |
288 | exit $ERRORS{'OK'}; | 308 | exit $ERRORS{'OK'}; |
@@ -297,68 +317,75 @@ sub process_arguments() { | |||
297 | $timeout = $TIMEOUT; | 317 | $timeout = $TIMEOUT; |
298 | } | 318 | } |
299 | 319 | ||
320 | if ($snmp_version !~ /[123]/){ | ||
321 | $state='UNKNOWN'; | ||
322 | print ("$state: No support for SNMP v$snmp_version yet\n"); | ||
323 | exit $ERRORS{$state}; | ||
324 | } | ||
325 | |||
326 | %session_opts = ( | ||
327 | -hostname => $hostname, | ||
328 | -port => $port, | ||
329 | -version => $snmp_version, | ||
330 | -maxmsgsize => $maxmsgsize | ||
331 | ); | ||
332 | |||
333 | $session_opts{'-community'} = $community if (defined $community && $snmp_version =~ /[12]/); | ||
334 | |||
300 | if ($snmp_version =~ /3/ ) { | 335 | if ($snmp_version =~ /3/ ) { |
301 | # Must define a security level even though default is noAuthNoPriv | 336 | # Must define a security level even though default is noAuthNoPriv |
302 | # v3 requires a security username | 337 | # v3 requires a security username |
303 | if (defined $seclevel && defined $secname) { | 338 | if (defined $seclevel && defined $secname) { |
339 | $session_opts{'-username'} = $secname; | ||
304 | 340 | ||
305 | # Must define a security level even though defualt is noAuthNoPriv | 341 | # Must define a security level even though defualt is noAuthNoPriv |
306 | unless ($seclevel eq ('noAuthNoPriv' || 'authNoPriv' || 'authPriv' ) ) { | 342 | unless ( grep /^$seclevel$/, qw(noAuthNoPriv authNoPriv authPriv) ) { |
307 | usage(); | 343 | usage("Must define a valid security level even though default is noAuthNoPriv"); |
308 | exit $ERRORS{"UNKNOWN"}; | ||
309 | } | 344 | } |
310 | 345 | ||
311 | # Authentication wanted | 346 | # Authentication wanted |
312 | if ($seclevel eq ('authNoPriv' || 'authPriv') ) { | 347 | if ( $seclevel eq 'authNoPriv' || $seclevel eq 'authPriv' ) { |
313 | 348 | if (defined $authproto && $authproto ne 'MD5' && $authproto ne 'SHA1') { | |
314 | unless ($authproto eq ('MD5' || 'SHA1') ) { | 349 | usage("Auth protocol can be either MD5 or SHA1"); |
315 | usage(); | ||
316 | exit $ERRORS{"UNKNOWN"}; | ||
317 | } | 350 | } |
351 | $session_opts{'-authprotocol'} = $authproto if(defined $authproto); | ||
318 | 352 | ||
319 | if ( !defined $authpass) { | 353 | if ( !defined $authpass) { |
320 | usage(); | 354 | usage("Auth password/key is not defined"); |
321 | exit $ERRORS{"UNKNOWN"}; | ||
322 | }else{ | 355 | }else{ |
323 | if ($authpass =~ /^0x/ ) { | 356 | if ($authpass =~ /^0x/ ) { |
324 | $auth = "-authkey => $authpass" ; | 357 | $session_opts{'-authkey'} = $authpass ; |
325 | }else{ | 358 | }else{ |
326 | $auth = "-authpassword => $authpass"; | 359 | $session_opts{'-authpassword'} = $authpass ; |
327 | } | 360 | } |
328 | } | 361 | } |
329 | |||
330 | } | 362 | } |
331 | 363 | ||
332 | # Privacy (DES encryption) wanted | 364 | # Privacy (DES encryption) wanted |
333 | if ($seclevel eq 'authPriv' ) { | 365 | if ($seclevel eq 'authPriv' ) { |
334 | if (! defined $privpass) { | 366 | if (! defined $privpass) { |
335 | usage(); | 367 | usage("Privacy passphrase/key is not defined"); |
336 | exit $ERRORS{"UNKNOWN"}; | ||
337 | }else{ | 368 | }else{ |
338 | if ($privpass =~ /^0x/){ | 369 | if ($privpass =~ /^0x/){ |
339 | $priv = "-privkey => $privpass"; | 370 | $session_opts{'-privkey'} = $privpass; |
340 | }else{ | 371 | }else{ |
341 | $priv = "-privpassword => $privpass"; | 372 | $session_opts{'-privpassword'} = $privpass; |
342 | } | 373 | } |
343 | } | 374 | } |
375 | |||
376 | $session_opts{'-privprotocol'} = $privproto if(defined $privproto); | ||
344 | } | 377 | } |
345 | 378 | ||
346 | # Context name defined or default | 379 | # Context name defined or default |
347 | |||
348 | unless ( defined $context) { | 380 | unless ( defined $context) { |
349 | $context = ""; | 381 | $context = ""; |
350 | } | 382 | } |
351 | 383 | ||
352 | |||
353 | |||
354 | }else { | 384 | }else { |
355 | usage(); | 385 | usage("Security level or name is not defined"); |
356 | exit $ERRORS{'UNKNOWN'}; ; | ||
357 | } | 386 | } |
358 | } # end snmpv3 | 387 | } # end snmpv3 |
359 | 388 | ||
360 | # for snmp v1 & v2c we default to community = "public" | ||
361 | |||
362 | # Excluded interfaces types (ifType) (backup interfaces, dial-on demand interfaces, PPP interfaces | 389 | # Excluded interfaces types (ifType) (backup interfaces, dial-on demand interfaces, PPP interfaces |
363 | if (defined $opt_x) { | 390 | if (defined $opt_x) { |
364 | my @x = split(/,/, $opt_x); | 391 | my @x = split(/,/, $opt_x); |
@@ -380,79 +407,16 @@ sub process_arguments() { | |||
380 | } | 407 | } |
381 | 408 | ||
382 | if (! utils::is_hostname($hostname)){ | 409 | if (! utils::is_hostname($hostname)){ |
383 | usage(); | 410 | usage("Hostname invalid or not given"); |
384 | exit $ERRORS{"UNKNOWN"}; | 411 | exit $ERRORS{"UNKNOWN"}; |
385 | } | 412 | } |
386 | 413 | ||
387 | # create SNMP session handle based on options passed. | ||
388 | |||
389 | if ( ! $snmp_version ) { | ||
390 | $snmp_version =1 ; | ||
391 | }else{ | ||
392 | if ( $snmp_version =~ /[12]/ ) { | ||
393 | |||
394 | ($session, $error) = Net::SNMP->session( | ||
395 | -hostname => $hostname, | ||
396 | -community => $community, | ||
397 | -port => $port, | ||
398 | -version => $snmp_version, | ||
399 | -maxmsgsize => $maxmsgsize | ||
400 | ); | ||
401 | |||
402 | if (!defined($session)) { | ||
403 | $state='UNKNOWN'; | ||
404 | $answer=$error; | ||
405 | print ("$state: $answer"); | ||
406 | exit $ERRORS{$state}; | ||
407 | } | ||
408 | |||
409 | 414 | ||
410 | }elsif ( $snmp_version =~ /3/ ) { | 415 | if ($snmp_version !~ /[123]/) { |
411 | |||
412 | if ($seclevel eq 'noAuthNoPriv') { | ||
413 | ($session, $error) = Net::SNMP->session( | ||
414 | -hostname => $hostname, | ||
415 | -port => $port, | ||
416 | -version => $snmp_version, | ||
417 | -username => $secname, | ||
418 | ); | ||
419 | |||
420 | }elsif ( $seclevel eq 'authNoPriv' ) { | ||
421 | ($session, $error) = Net::SNMP->session( | ||
422 | -hostname => $hostname, | ||
423 | -port => $port, | ||
424 | -version => $snmp_version, | ||
425 | -username => $secname, | ||
426 | -authprotocol => $authproto, | ||
427 | $auth | ||
428 | ); | ||
429 | }elsif ($seclevel eq 'authPriv' ) { | ||
430 | ($session, $error) = Net::SNMP->session( | ||
431 | -hostname => $hostname, | ||
432 | -port => $port, | ||
433 | -version => $snmp_version, | ||
434 | -username => $secname, | ||
435 | -authprotocol => $authproto, | ||
436 | $auth, | ||
437 | $priv | ||
438 | ); | ||
439 | } | ||
440 | |||
441 | |||
442 | if (!defined($session)) { | ||
443 | $state='UNKNOWN'; | ||
444 | $answer=$error; | ||
445 | print ("$state: $answer"); | ||
446 | exit $ERRORS{$state}; | ||
447 | } | ||
448 | |||
449 | }else{ | ||
450 | $state='UNKNOWN'; | 416 | $state='UNKNOWN'; |
451 | print ("$state: No support for SNMP v$snmp_version yet\n"); | 417 | print ("$state: No support for SNMP v$snmp_version yet\n"); |
452 | exit $ERRORS{$state}; | 418 | exit $ERRORS{$state}; |
453 | } | 419 | } |
454 | } | ||
455 | 420 | ||
456 | return $ERRORS{"OK"}; | 421 | return $ERRORS{"OK"}; |
457 | |||
458 | } | 422 | } |
diff --git a/plugins-scripts/t/check_ifstatus.t b/plugins-scripts/t/check_ifstatus.t new file mode 100644 index 0000000..c5169d9 --- /dev/null +++ b/plugins-scripts/t/check_ifstatus.t | |||
@@ -0,0 +1,63 @@ | |||
1 | #! /usr/bin/perl -w -I .. | ||
2 | # | ||
3 | # SNMP Test via check_ifoperstatus | ||
4 | # | ||
5 | # | ||
6 | |||
7 | use strict; | ||
8 | use Test::More; | ||
9 | use NPTest; | ||
10 | |||
11 | my $tests = 9; | ||
12 | plan tests => $tests; | ||
13 | my $res; | ||
14 | |||
15 | my $plugin = "check_ifstatus"; | ||
16 | SKIP: { | ||
17 | skip "$plugin is not created", $tests if ( ! -x $plugin ); | ||
18 | |||
19 | my $host_snmp = getTestParameter( "host_snmp", "NP_HOST_SNMP", "localhost", | ||
20 | "A host providing an SNMP Service"); | ||
21 | |||
22 | my $snmp_community = getTestParameter( "snmp_community", "NP_SNMP_COMMUNITY", "public", | ||
23 | "The SNMP Community string for SNMP Testing (assumes snmp v1)" ); | ||
24 | |||
25 | my $host_nonresponsive = getTestParameter( "host_nonresponsive", "NP_HOST_NONRESPONSIVE", "10.0.0.1", | ||
26 | "The hostname of system not responsive to network requests" ); | ||
27 | |||
28 | my $hostname_invalid = getTestParameter( "hostname_invalid", "NP_HOSTNAME_INVALID", "nosuchhost", | ||
29 | "An invalid (not known to DNS) hostname" ); | ||
30 | |||
31 | $res = NPTest->testCmd( "./$plugin" ); | ||
32 | is( $res->return_code, 3, "No arguments" ); | ||
33 | like( $res->output, '/usage/', "Output contains usage" ); | ||
34 | |||
35 | $res = NPTest->testCmd( "./$plugin -H fakehost -v 3 --seclevel rubbish --secname foobar" ); | ||
36 | is( $res->return_code, 3, "invalid seclevel" ); | ||
37 | like( $res->output, "/Must define a valid security level/", "Output contains 'Must define a valid security level'" ); | ||
38 | |||
39 | SKIP: { | ||
40 | skip "no snmp host defined", 2 if ( ! $host_snmp ); | ||
41 | |||
42 | $res = NPTest->testCmd( "./$plugin -H $host_snmp -C $snmp_community "); | ||
43 | like($res->output, '/^.*host.*interfaces up/', "String contains host.*interfaces up"); | ||
44 | |||
45 | $res = NPTest->testCmd( "./$plugin -H $host_snmp -C rubbish"); | ||
46 | cmp_ok( $res->return_code, '==', 2, "Exit CRITICAL for community 'rubbish'" ); | ||
47 | |||
48 | } | ||
49 | |||
50 | SKIP: { | ||
51 | skip "no non responsive host defined", 1 if ( ! $host_nonresponsive ); | ||
52 | $res = NPTest->testCmd( "./$plugin -H $host_nonresponsive -C $snmp_community"); | ||
53 | cmp_ok( $res->return_code, '==', 2, "Exit CRITICAL with non responsive host" ); | ||
54 | } | ||
55 | |||
56 | SKIP: { | ||
57 | skip "no invalid host defined", 2 if ( ! $hostname_invalid ); | ||
58 | $res = NPTest->testCmd( "./$plugin -H $hostname_invalid -C $snmp_community"); | ||
59 | cmp_ok( $res->return_code, '==', 3, "Exit UNKNOWN with invalid host" ); | ||
60 | like($res->output, "/Unable to resolve.*$hostname_invalid/", "String matches unable to resolve.*$hostname_invalid"); | ||
61 | } | ||
62 | |||
63 | } | ||