diff options
Diffstat (limited to 'plugins-scripts/check_ifstatus.pl')
-rwxr-xr-x | plugins-scripts/check_ifstatus.pl | 323 |
1 files changed, 230 insertions, 93 deletions
diff --git a/plugins-scripts/check_ifstatus.pl b/plugins-scripts/check_ifstatus.pl index cc9cccf..3372adb 100755 --- a/plugins-scripts/check_ifstatus.pl +++ b/plugins-scripts/check_ifstatus.pl | |||
@@ -7,6 +7,8 @@ | |||
7 | # Modified 5/2002 to conform to updated Nagios Plugin Guidelines (S. Ghosh) | 7 | # Modified 5/2002 to conform to updated Nagios Plugin Guidelines (S. Ghosh) |
8 | # Added -x option (4/2003) | 8 | # Added -x option (4/2003) |
9 | # Added -u option (4/2003) | 9 | # Added -u option (4/2003) |
10 | # Added -M option (10/2003) | ||
11 | # Added SNMPv3 support (10/2003) | ||
10 | # | 12 | # |
11 | # This program is free software; you can redistribute it and/or | 13 | # This program is free software; you can redistribute it and/or |
12 | # modify it under the terms of the GNU General Public License | 14 | # modify it under the terms of the GNU General Public License |
@@ -40,9 +42,13 @@ Getopt::Long::Configure('bundling'); | |||
40 | 42 | ||
41 | my $PROGNAME = "check_ifstatus"; | 43 | my $PROGNAME = "check_ifstatus"; |
42 | 44 | ||
45 | sub print_help (); | ||
46 | sub usage (); | ||
47 | sub process_arguments (); | ||
48 | |||
43 | 49 | ||
44 | my $status; | 50 | my $status; |
45 | my %ifOperStatus = ('1','up', | 51 | my %ifOperStatus = ('1','up', |
46 | '2','down', | 52 | '2','down', |
47 | '3','testing', | 53 | '3','testing', |
48 | '4','unknown', | 54 | '4','unknown', |
@@ -55,6 +61,8 @@ my $snmpkey=0; | |||
55 | my $snmpoid=0; | 61 | my $snmpoid=0; |
56 | my $key=0; | 62 | my $key=0; |
57 | my $community = "public"; | 63 | my $community = "public"; |
64 | my $maxmsgsize = 1472 ; # Net::SNMP default is 1472 | ||
65 | my ($seclevel, $authproto, $secname, $authpass, $privpass, $auth, $priv, $context); | ||
58 | my $port = 161; | 66 | my $port = 161; |
59 | my @snmpoids; | 67 | my @snmpoids; |
60 | my $snmpIfAdminStatus = '1.3.6.1.2.1.2.2.1.7'; | 68 | my $snmpIfAdminStatus = '1.3.6.1.2.1.2.2.1.7'; |
@@ -93,98 +101,19 @@ $SIG{'ALRM'} = sub { | |||
93 | print ("ERROR: No snmp response from $hostname (alarm timeout)\n"); | 101 | print ("ERROR: No snmp response from $hostname (alarm timeout)\n"); |
94 | exit $ERRORS{"UNKNOWN"}; | 102 | exit $ERRORS{"UNKNOWN"}; |
95 | }; | 103 | }; |
96 | alarm($TIMEOUT); | ||
97 | |||
98 | 104 | ||
99 | 105 | ||
100 | #Option checking | 106 | #Option checking |
101 | $status = GetOptions( | 107 | $status = process_arguments(); |
102 | "V" => \$opt_V, "version" => \$opt_V, | 108 | |
103 | "h" => \$opt_h, "help" => \$opt_h, | 109 | if ($status != 0) |
104 | "v=i" => \$snmp_version, "snmp_version=i" => \$snmp_version, | ||
105 | "C=s" =>\$community,"community=s" => \$community, | ||
106 | "p=i" =>\$port, "port=i" => \$port, | ||
107 | "H=s" => \$hostname, "hostname=s" => \$hostname, | ||
108 | "I" => \$ifXTable, "ifmib" => \$ifXTable, | ||
109 | "x:s" => \$opt_x, "exclude:s" => \$opt_x, | ||
110 | "u=s" => \$opt_u, "unused_ports=s" => \$opt_u); | ||
111 | |||
112 | if ($status == 0) | ||
113 | { | 110 | { |
114 | print_help() ; | 111 | print_help() ; |
115 | exit $ERRORS{'OK'}; | 112 | exit $ERRORS{'OK'}; |
116 | } | 113 | } |
117 | 114 | ||
118 | 115 | ||
119 | if ($opt_V) { | 116 | alarm($TIMEOUT); |
120 | print_revision($PROGNAME,'$Revision$ '); | ||
121 | exit $ERRORS{'OK'}; | ||
122 | } | ||
123 | |||
124 | if ($opt_h) { | ||
125 | print_help(); | ||
126 | exit $ERRORS{'OK'}; | ||
127 | } | ||
128 | |||
129 | |||
130 | if (defined $opt_x) { | ||
131 | my @x = split(/,/, $opt_x); | ||
132 | if ( @x) { | ||
133 | foreach $key (@x){ | ||
134 | $excluded{$key} = 1; | ||
135 | } | ||
136 | }else{ | ||
137 | $excluded{23} = 1; # default PPP(23) if empty list - note (AIX seems to think PPP is 22 according to a post) | ||
138 | } | ||
139 | #debugging | ||
140 | #foreach $x (keys %excluded) | ||
141 | # { print "key = $x val = $excluded{$x}\n";} | ||
142 | } | ||
143 | |||
144 | if ($opt_u) { | ||
145 | @unused_ports = split(/,/,$opt_u); | ||
146 | foreach $key (@unused_ports) { | ||
147 | $ifStatus{$key}{'notInUse'}++ ; | ||
148 | } | ||
149 | } | ||
150 | |||
151 | if (! utils::is_hostname($hostname)){ | ||
152 | usage(); | ||
153 | exit $ERRORS{"UNKNOWN"}; | ||
154 | } | ||
155 | |||
156 | if ( ! $snmp_version ) { | ||
157 | $snmp_version =1 ; | ||
158 | }else{ | ||
159 | if ( $snmp_version =~ /[12]/ ) { | ||
160 | |||
161 | ($session, $error) = Net::SNMP->session( | ||
162 | -hostname => $hostname, | ||
163 | -community => $community, | ||
164 | -port => $port, | ||
165 | -version => $snmp_version | ||
166 | ); | ||
167 | |||
168 | if (!defined($session)) { | ||
169 | $state='UNKNOWN'; | ||
170 | $answer=$error; | ||
171 | print ("$state: $answer"); | ||
172 | exit $ERRORS{$state}; | ||
173 | } | ||
174 | |||
175 | |||
176 | }elsif ( $snmp_version =~ /3/ ) { | ||
177 | $state='UNKNOWN'; | ||
178 | print ("$state: No support for SNMP v3 yet\n"); | ||
179 | exit $ERRORS{$state}; | ||
180 | }else{ | ||
181 | $state='UNKNOWN'; | ||
182 | print ("$state: No support for SNMP v$snmp_version yet\n"); | ||
183 | exit $ERRORS{$state}; | ||
184 | } | ||
185 | } | ||
186 | |||
187 | |||
188 | 117 | ||
189 | push(@snmpoids,$snmpIfOperStatus); | 118 | push(@snmpoids,$snmpIfOperStatus); |
190 | push(@snmpoids,$snmpIfAdminStatus); | 119 | push(@snmpoids,$snmpIfAdminStatus); |
@@ -205,7 +134,7 @@ foreach $snmpoid (@snmpoids) { | |||
205 | if ( ( $snmpoid =~ $snmpIfName ) && defined $ifXTable ) { | 134 | if ( ( $snmpoid =~ $snmpIfName ) && defined $ifXTable ) { |
206 | print ("$state: Device does not support ifTable - try without -I option\n"); | 135 | print ("$state: Device does not support ifTable - try without -I option\n"); |
207 | }else{ | 136 | }else{ |
208 | print ("$state: $answer for $snmpoid with snmp version $snmp_version\n"); | 137 | print ("$state: $answer for $snmpoid with snmp version $snmp_version\n"); |
209 | } | 138 | } |
210 | exit $ERRORS{$state}; | 139 | exit $ERRORS{$state}; |
211 | } | 140 | } |
@@ -220,6 +149,8 @@ foreach $snmpoid (@snmpoids) { | |||
220 | 149 | ||
221 | $session->close; | 150 | $session->close; |
222 | 151 | ||
152 | alarm(0); | ||
153 | |||
223 | foreach $key (keys %ifStatus) { | 154 | foreach $key (keys %ifStatus) { |
224 | 155 | ||
225 | # skip unused interfaces | 156 | # skip unused interfaces |
@@ -230,18 +161,18 @@ foreach $key (keys %ifStatus) { | |||
230 | # check only if interface type is not listed in %excluded | 161 | # check only if interface type is not listed in %excluded |
231 | if (!defined $excluded{$ifStatus{$key}{$snmpIfType}} ) { | 162 | if (!defined $excluded{$ifStatus{$key}{$snmpIfType}} ) { |
232 | if ($ifStatus{$key}{$snmpIfOperStatus} == 1 ) { $ifup++ ;} | 163 | if ($ifStatus{$key}{$snmpIfOperStatus} == 1 ) { $ifup++ ;} |
233 | if ($ifStatus{$key}{$snmpIfOperStatus} == 2 ) { | 164 | if ($ifStatus{$key}{$snmpIfOperStatus} == 2 ) { |
234 | $ifdown++ ; | 165 | $ifdown++ ; |
235 | if (defined $ifXTable) { | 166 | if (defined $ifXTable) { |
236 | $ifmessage .= sprintf("%s: down -> %s<BR>", | 167 | $ifmessage .= sprintf("%s: down -> %s<BR>", |
237 | $ifStatus{$key}{$snmpIfName}, | 168 | $ifStatus{$key}{$snmpIfName}, |
238 | $ifStatus{$key}{$snmpIfAlias}); | 169 | $ifStatus{$key}{$snmpIfAlias}); |
239 | }else{ | 170 | }else{ |
240 | $ifmessage .= sprintf("%s: down <BR>", | 171 | $ifmessage .= sprintf("%s: down <BR>", |
241 | $ifStatus{$key}{$snmpIfDescr}); | 172 | $ifStatus{$key}{$snmpIfDescr}); |
242 | } | 173 | } |
243 | } | 174 | } |
244 | if ($ifStatus{$key}{$snmpIfOperStatus} == 5 ) { $ifdormant++ ;} | 175 | if ($ifStatus{$key}{$snmpIfOperStatus} == 5 ) { $ifdormant++ ;} |
245 | }else{ | 176 | }else{ |
246 | $ifexclude++; | 177 | $ifexclude++; |
247 | } | 178 | } |
@@ -278,7 +209,7 @@ print ("$state: $answer |$perfdata\n"); | |||
278 | exit $ERRORS{$state}; | 209 | exit $ERRORS{$state}; |
279 | 210 | ||
280 | 211 | ||
281 | sub usage { | 212 | sub usage (){ |
282 | printf "\nMissing arguments!\n"; | 213 | printf "\nMissing arguments!\n"; |
283 | printf "\n"; | 214 | printf "\n"; |
284 | printf "check_ifstatus -C <READCOMMUNITY> -p <PORT> -H <HOSTNAME>\n"; | 215 | printf "check_ifstatus -C <READCOMMUNITY> -p <PORT> -H <HOSTNAME>\n"; |
@@ -289,24 +220,230 @@ sub usage { | |||
289 | exit $ERRORS{"UNKNOWN"}; | 220 | exit $ERRORS{"UNKNOWN"}; |
290 | } | 221 | } |
291 | 222 | ||
292 | sub print_help { | 223 | sub print_help (){ |
293 | printf "check_ifstatus plugin for Nagios monitors operational \n"; | 224 | printf "check_ifstatus plugin for Nagios monitors operational \n"; |
294 | printf "status of each network interface on the target host\n"; | 225 | printf "status of each network interface on the target host\n"; |
295 | printf "\nUsage:\n"; | 226 | printf "\nUsage:\n"; |
296 | printf " -H (--hostname) Hostname to query - (required)\n"; | 227 | printf " -H (--hostname) Hostname to query - (required)\n"; |
297 | printf " -C (--community) SNMP read community (defaults to public,\n"; | 228 | printf " -C (--community) SNMP read community (defaults to public,\n"; |
298 | printf " used with SNMP v1 and v2c\n"; | 229 | printf " used with SNMP v1 and v2c\n"; |
299 | printf " -v (--snmp_version) 1 for SNMP v1 (default)\n"; | 230 | printf " -v (--snmp_version) 1 for SNMP v1 (default)\n"; |
300 | printf " 2 for SNMP v2c\n"; | 231 | printf " 2 for SNMP v2c\n"; |
301 | printf " SNMP v2c will use get_bulk for less overhead\n"; | 232 | printf " SNMP v2c will use get_bulk for less overhead\n"; |
233 | printf " 3 for SNMPv3 (requires -U option)"; | ||
302 | printf " -p (--port) SNMP port (default 161)\n"; | 234 | printf " -p (--port) SNMP port (default 161)\n"; |
303 | printf " -I (--ifmib) Agent supports IFMIB ifXTable. For Cisco - this will provide\n"; | 235 | printf " -I (--ifmib) Agent supports IFMIB ifXTable. For Cisco - this will provide\n"; |
304 | printf " the descriptive name. Do not use if you don't know what this is. \n"; | 236 | printf " the descriptive name. Do not use if you don't know what this is. \n"; |
305 | printf " -x (--exclude) A comma separated list of ifType values that should be excluded \n"; | 237 | printf " -x (--exclude) A comma separated list of ifType values that should be excluded \n"; |
306 | printf " from the report (default for an empty list is PPP(23).\n"; | 238 | printf " from the report (default for an empty list is PPP(23).\n"; |
239 | printf " -u (--unused_ports) A comma separated list of ifIndex values that should be excluded \n"; | ||
240 | printf " from the report (default is an empty exclusion list).\n"; | ||
307 | printf " See the IANAifType-MIB for a list of interface types.\n"; | 241 | printf " See the IANAifType-MIB for a list of interface types.\n"; |
242 | printf " -L (--seclevel) choice of \"noAuthNoPriv\", \"authNoPriv\", or \"authPriv\"\n"; | ||
243 | printf " -U (--secname) username for SNMPv3 context\n"; | ||
244 | printf " -c (--context) SNMPv3 context name (default is empty string)"; | ||
245 | printf " -A (--authpass) authentication password (cleartext ascii or localized key\n"; | ||
246 | printf " in hex with 0x prefix generated by using \"snmpkey\" utility\n"; | ||
247 | printf " auth password and authEngineID\n"; | ||
248 | printf " -a (--authproto) Authentication protocol ( MD5 or SHA1)\n"; | ||
249 | printf " -X (--privpass) privacy password (cleartext ascii or localized key\n"; | ||
250 | printf " in hex with 0x prefix generated by using \"snmpkey\" utility\n"; | ||
251 | printf " privacy password and authEngineID\n"; | ||
252 | printf " -M (--maxmsgsize) Max message size - usefull only for v1 or v2c\n"; | ||
308 | printf " -V (--version) Plugin version\n"; | 253 | printf " -V (--version) Plugin version\n"; |
309 | printf " -h (--help) usage help \n\n"; | 254 | printf " -h (--help) usage help \n\n"; |
310 | print_revision($PROGNAME, '$Revision$'); | 255 | print_revision($PROGNAME, '$Revision$'); |
311 | 256 | ||
312 | } | 257 | } |
258 | |||
259 | sub process_arguments() { | ||
260 | $status = GetOptions( | ||
261 | "V" => \$opt_V, "version" => \$opt_V, | ||
262 | "h" => \$opt_h, "help" => \$opt_h, | ||
263 | "v=i" => \$snmp_version, "snmp_version=i" => \$snmp_version, | ||
264 | "C=s" => \$community,"community=s" => \$community, | ||
265 | "L=s" => \$seclevel, "seclevel=s" => \$seclevel, | ||
266 | "a=s" => \$authproto, "authproto=s" => \$authproto, | ||
267 | "U=s" => \$secname, "secname=s" => \$secname, | ||
268 | "A=s" => \$authpass, "authpass=s" => \$authpass, | ||
269 | "X=s" => \$privpass, "privpass=s" => \$privpass, | ||
270 | "c=s" => \$context, "context=s" => \$context, | ||
271 | "p=i" =>\$port, "port=i" => \$port, | ||
272 | "H=s" => \$hostname, "hostname=s" => \$hostname, | ||
273 | "I" => \$ifXTable, "ifmib" => \$ifXTable, | ||
274 | "x:s" => \$opt_x, "exclude:s" => \$opt_x, | ||
275 | "u=s" => \$opt_u, "unused_ports=s" => \$opt_u, | ||
276 | "M=i" => \$maxmsgsize, "maxmsgsize=i" => \$maxmsgsize); | ||
277 | |||
278 | if ($status == 0){ | ||
279 | print_help() ; | ||
280 | exit $ERRORS{'OK'}; | ||
281 | } | ||
282 | if ($opt_V) { | ||
283 | print_revision($PROGNAME,'$Revision$ '); | ||
284 | exit $ERRORS{'OK'}; | ||
285 | } | ||
286 | |||
287 | if ($opt_h) { | ||
288 | print_help(); | ||
289 | exit $ERRORS{'OK'}; | ||
290 | } | ||
291 | |||
292 | |||
293 | if ($snmp_version =~ /3/ ) { | ||
294 | # Must define a security level even though default is noAuthNoPriv | ||
295 | # v3 requires a security username | ||
296 | if (defined $seclevel && defined $secname) { | ||
297 | |||
298 | # Must define a security level even though defualt is noAuthNoPriv | ||
299 | unless ($seclevel eq ('noAuthNoPriv' || 'authNoPriv' || 'authPriv' ) ) { | ||
300 | usage(); | ||
301 | exit $ERRORS{"UNKNOWN"}; | ||
302 | } | ||
303 | |||
304 | # Authentication wanted | ||
305 | if ($seclevel eq ('authNoPriv' || 'authPriv') ) { | ||
306 | |||
307 | unless ($authproto eq ('MD5' || 'SHA1') ) { | ||
308 | usage(); | ||
309 | exit $ERRORS{"UNKNOWN"}; | ||
310 | } | ||
311 | |||
312 | if ( !defined $authpass) { | ||
313 | usage(); | ||
314 | exit $ERRORS{"UNKNOWN"}; | ||
315 | }else{ | ||
316 | if ($authpass =~ /^0x/ ) { | ||
317 | $auth = "-authkey => $authpass" ; | ||
318 | }else{ | ||
319 | $auth = "-authpassword => $authpass"; | ||
320 | } | ||
321 | } | ||
322 | |||
323 | } | ||
324 | |||
325 | # Privacy (DES encryption) wanted | ||
326 | if ($seclevel eq 'authPriv' ) { | ||
327 | if (! defined $privpass) { | ||
328 | usage(); | ||
329 | exit $ERRORS{"UNKNOWN"}; | ||
330 | }else{ | ||
331 | if ($privpass =~ /^0x/){ | ||
332 | $priv = "-privkey => $privpass"; | ||
333 | }else{ | ||
334 | $priv = "-privpassword => $privpass"; | ||
335 | } | ||
336 | } | ||
337 | } | ||
338 | |||
339 | # Context name defined or default | ||
340 | |||
341 | unless ( defined $context) { | ||
342 | $context = ""; | ||
343 | } | ||
344 | |||
345 | |||
346 | |||
347 | }else { | ||
348 | usage(); | ||
349 | exit $ERRORS{'UNKNOWN'}; ; | ||
350 | } | ||
351 | } # end snmpv3 | ||
352 | |||
353 | # for snmp v1 & v2c we default to community = "public" | ||
354 | |||
355 | # Excluded interfaces types (ifType) (backup interfaces, dial-on demand interfaces, PPP interfaces | ||
356 | if (defined $opt_x) { | ||
357 | my @x = split(/,/, $opt_x); | ||
358 | if ( @x) { | ||
359 | foreach $key (@x){ | ||
360 | $excluded{$key} = 1; | ||
361 | } | ||
362 | }else{ | ||
363 | $excluded{23} = 1; # default PPP(23) if empty list - note (AIX seems to think PPP is 22 according to a post) | ||
364 | } | ||
365 | } | ||
366 | |||
367 | # Excluded interface ports (ifIndex) - management reasons | ||
368 | if ($opt_u) { | ||
369 | @unused_ports = split(/,/,$opt_u); | ||
370 | foreach $key (@unused_ports) { | ||
371 | $ifStatus{$key}{'notInUse'}++ ; | ||
372 | } | ||
373 | } | ||
374 | |||
375 | if (! utils::is_hostname($hostname)){ | ||
376 | usage(); | ||
377 | exit $ERRORS{"UNKNOWN"}; | ||
378 | } | ||
379 | |||
380 | # create SNMP session handle based on options passed. | ||
381 | |||
382 | if ( ! $snmp_version ) { | ||
383 | $snmp_version =1 ; | ||
384 | }else{ | ||
385 | if ( $snmp_version =~ /[12]/ ) { | ||
386 | |||
387 | ($session, $error) = Net::SNMP->session( | ||
388 | -hostname => $hostname, | ||
389 | -community => $community, | ||
390 | -port => $port, | ||
391 | -version => $snmp_version, | ||
392 | -maxmsgsize => $maxmsgsize | ||
393 | ); | ||
394 | |||
395 | if (!defined($session)) { | ||
396 | $state='UNKNOWN'; | ||
397 | $answer=$error; | ||
398 | print ("$state: $answer"); | ||
399 | exit $ERRORS{$state}; | ||
400 | } | ||
401 | |||
402 | |||
403 | }elsif ( $snmp_version =~ /3/ ) { | ||
404 | |||
405 | if ($seclevel eq 'noAuthNoPriv') { | ||
406 | ($session, $error) = Net::SNMP->session( | ||
407 | -hostname => $hostname, | ||
408 | -port => $port, | ||
409 | -version => $snmp_version, | ||
410 | -username => $secname, | ||
411 | ); | ||
412 | |||
413 | }elsif ( $seclevel eq 'authNoPriv' ) { | ||
414 | ($session, $error) = Net::SNMP->session( | ||
415 | -hostname => $hostname, | ||
416 | -port => $port, | ||
417 | -version => $snmp_version, | ||
418 | -username => $secname, | ||
419 | $auth | ||
420 | ); | ||
421 | }elsif ($seclevel eq 'authPriv' ) { | ||
422 | ($session, $error) = Net::SNMP->session( | ||
423 | -hostname => $hostname, | ||
424 | -port => $port, | ||
425 | -version => $snmp_version, | ||
426 | -username => $secname, | ||
427 | $auth, | ||
428 | $priv | ||
429 | ); | ||
430 | } | ||
431 | |||
432 | |||
433 | if (!defined($session)) { | ||
434 | $state='UNKNOWN'; | ||
435 | $answer=$error; | ||
436 | print ("$state: $answer"); | ||
437 | exit $ERRORS{$state}; | ||
438 | } | ||
439 | |||
440 | }else{ | ||
441 | $state='UNKNOWN'; | ||
442 | print ("$state: No support for SNMP v$snmp_version yet\n"); | ||
443 | exit $ERRORS{$state}; | ||
444 | } | ||
445 | } | ||
446 | |||
447 | return $ERRORS{"OK"}; | ||
448 | |||
449 | } | ||