#!/usr/bin/perl -T use warnings; use strict; use Nagios::Plugin; $ENV{'PATH'} = '/bin:/usr/bin:/sbin:/usr/sbin'; delete @ENV{'IFS', 'CDPATH', 'ENV', 'BASH_ENV'}; my $n = Nagios::Plugin->new; # Check the status of the given network interface and return # three lists of the interfaces sorted by status (all, down, error). # This does resolves interfaces groups automaticaly and returns # the member interfaces. # # parameter: # list of interfaces sub get_if_status (@) { my (@all, @down, @error); while (@_) { # untaint interface name my $if = shift @_; next unless ($if =~ m/^([-\w]+)$/); $if = $1; # We are doing an two step process. First we do a fork and # after that we exec the ifconfig child process. This is # necessary to pipe stderr of the child process away, while # using the list syntax for open and exec. my $pid = open(IFCONFIG, "-|"); $n->nagois_exit(CRITICAL, "fork: $!") unless defined $pid; if ($pid == 0) { # redirect stderr open(STDERR, ">", "/dev/null"); exec("ifconfig", $if) } while () { # parse ifconfig output: if ($_ =~ m/^([-a-v0-9]+): flags=([0-9]+)) { if ($_ =~ m{In4/Pass.*Bytes: ([0-9]+)}) { $stats->{'in4'} = $1; } elsif ($_ =~ m{Out4/Pass.*Bytes: ([0-9]+)}) { $stats->{'out4'} = $1; } elsif ($_ =~ m{In6/Pass.*Bytes: ([0-9]+)}) { $stats->{'in6'} = $1; } elsif ($_ =~ m{Out6/Pass.*Bytes: ([0-9]+)}) { $stats->{'out6'} = $1; } } close(PFCTL); return $stats; } # Print nagios compatible message containing the number of interfaces # and performance data containing the byte counter for the interfaces. # # parameter: # nagios status code # additional message # interface statistics sub print_stats ($$$) { my $status = shift; my $msg = shift; my $stats = shift; my ($count, $perfdata); $count = keys %$stats; $perfdata = ""; for my $if (keys %$stats) { for (qw( in4 out4 in6 out6 )) { $perfdata = "$perfdata $if-$_=$stats->{$if}->{$_};"; } } $n->nagios_exit($status, "$count interfaces$msg |$perfdata"); } # This function generate a nagios status code and an additional # message, based on the counts of the interfaces, that are down # or does not exist. # # parameter: # list of down interfaces # list of interfaces, that does not exists # returns: # (status, msg) for nagios sub get_status ($$) { my $down = shift; my $error = shift; my ($status, $msg) = (OK, ''); # Order matters! LAST MATCH WINS. if (@$down) { # Chech whether some interfaces are down and we have to # issue a warning. my $count = @$down; $down = join ", ", @$down; $status = WARNING; $msg = ", $count interface(s) are down ($down)"; } if (@$error) { # Chech whether some interface or interface group, specified # on the command line, does not exists and we should return a # critical error. my $count = @$error; $error = join ", ", @$error; $status = CRITICAL; $msg = ", $count interface(s) does not exists ($error)"; } return ($status, $msg); } my ($interfaces, $down, $error) = get_if_status(@ARGV); my ($status, $msg) = get_status($down, $error); my $stats = {}; for my $if (@$interfaces) { $stats->{$if} = get_if_stats($if); } print_stats($status, $msg, $stats); $n->nagios_exit(CRITICAL, "End of script");