version 1.2, 2009/11/13 22:23:24 |
version 1.5, 2009/11/19 21:35:32 |
|
|
#!/usr/bin/perl -T |
#!/usr/bin/perl -T |
# $RedRiver: check_openbgpd,v 1.1 2009/11/13 02:05:20 andrew Exp $ |
# $RedRiver: check_openbgpd,v 1.4 2009/11/19 21:22:01 andrew Exp $ |
######################################################################## |
######################################################################## |
# check_openbgpd *** A nagios check for OpenBSD bgpd |
# check_openbgpd *** A nagios check for OpenBSD bgpd |
# |
# |
|
|
exit $ERRORS{'OK'}; |
exit $ERRORS{'OK'}; |
} |
} |
|
|
my @STATUS = read_status(); |
my @STATUS = read_status( $CHECKS{_SOCKET} ); |
my %STATES = check_status( \@STATUS, \%CHECKS ); |
my %STATES = check_status( \@STATUS, \%CHECKS ); |
|
|
my $have_results = 0; |
my $have_results = 0; |
|
|
exit $ERRORS{$state}; |
exit $ERRORS{$state}; |
|
|
sub read_status { |
sub read_status { |
my ($status) = @_; |
my ($socket) = @_; |
my @S; |
my @S; |
|
|
|
my @cmd = ($BGPCTL); |
|
if ($socket) { |
|
push @cmd, '-s', $socket; |
|
} |
|
push @cmd, 'show', 'summary'; |
|
|
#open my $fh, '<', 'output' # XXX |
#open my $fh, '<', 'output' # XXX |
open my $fh, '-|', $BGPCTL, 'show', 'summary' |
open my $fh, '-|', @cmd or die "Couldn't open bgpctl: $!\n"; |
or die "Couldn't open bgpctl: $!\n"; |
|
while (<$fh>) { |
while (<$fh>) { |
chomp; |
chomp; |
push @S, parse_line($_); |
push @S, parse_line($_); |
|
|
|
|
foreach my $d ( 'low', 'high' ) { |
foreach my $d ( 'low', 'high' ) { |
if ( defined $c{$d} ) { |
if ( defined $c{$d} ) { |
$c{$d} =~ s/[^-\d\.]//gxms; |
$c{$d} =~ s/[^-\d\.\%]//gxms; |
if ( !length $c{$d} ) { |
if ( !length $c{$d} ) { |
delete $c{$d}; |
delete $c{$d}; |
} |
} |
|
|
my ( $S, $C ) = @_; |
my ( $S, $C ) = @_; |
|
|
my %states; |
my %states; |
my %neighbors; |
my %neighbors = map { $_ => $C->{$_} } qw( _SOCKET _UNKNOWN ); |
STATE: foreach my $s ( @{$S} ) { |
STATE: foreach my $s ( @{$S} ) { |
my $n = $s->{neighbor}; |
my $n = $s->{neighbor}; |
$neighbors{$n} = $s; |
$neighbors{$n} = $s; |
|
|
my $result; |
my $result; |
|
|
if ( my $c = $C->{$n} ) { |
if ( my $c = $C->{$n} || $C->{_UNKNOWN} ) { |
CODE: foreach my $code ( 'CRITICAL', 'WARNING' ) { |
CODE: foreach my $code ( 'CRITICAL', 'WARNING' ) { |
next CODE if ( ref $c->{$code} ne 'HASH' ); |
next CODE if ( ref $c->{$code} ne 'HASH' ); |
my $data = $s->{state}; |
my $data = $s->{state}; |
|
|
|
|
if ( $c->{low} || $c->{high} ) { |
if ( $c->{low} || $c->{high} ) { |
$result = undef; |
$result = undef; |
my $num = $d; |
my ( $num, $max ) = split m{/}xms, $d; |
$num =~ s/[^-\d\.]//gxms; |
$num =~ s/[^-\d\.]//gxms; |
|
|
if ( !length $num ) { |
if ( !length $num ) { |
return 'State (' . $d . ') is not numeric'; |
return 'State (' . $d . ') is not numeric'; |
} |
} |
|
|
if ( $c->{low} && $num < $c->{low} ) { |
DIRECTION: foreach my $dir qw( low high ) { |
return 'is below threshold (' . $d . ' < ' . $c->{low} . ')'; |
if ( !$c->{$dir} ) { next DIRECTION; } |
} |
|
|
|
if ( $c->{high} && $num > $c->{high} ) { |
my $check = $c->{$dir}; |
return 'is above threshold (' . $d . ' > ' . $c->{high} . ')'; |
my $cnum = $num; |
|
|
|
if ( $check =~ s/\%$//xms ) { |
|
if ( !defined $max ) { |
|
return 'max-prefix not specified and % check requested'; |
|
} |
|
|
|
# convert to percent |
|
$cnum = 100 * $cnum / $max; |
|
} |
|
|
|
my @nums = ( $cnum, $check ); |
|
my $abovebelow = 'below'; |
|
my $symbol = '<'; |
|
if ( $dir eq 'high' ) { |
|
@nums = ( $check, $cnum ); |
|
$abovebelow = 'above'; |
|
$symbol = '>'; |
|
} |
|
|
|
if ( $nums[0] < $nums[1] ) { |
|
return join q{ }, 'is', $abovebelow, |
|
'threshold (' . $d, |
|
$symbol, $c->{$dir} . ')'; |
|
} |
} |
} |
} |
} |
|
|
|
|
exit $ERRORS{'OK'} |
exit $ERRORS{'OK'} |
} |
} |
when (/^-?-h(?:elp)?/xms) { print_help(); exit $ERRORS{'OK'} } |
when (/^-?-h(?:elp)?/xms) { print_help(); exit $ERRORS{'OK'} } |
|
when (/^-?-s(?:ocket)?/xms) { $checks{_SOCKET} = shift @argv } |
when (/^-?-w(?:arning)?/xms) { $w = parse_check( shift @argv ) } |
when (/^-?-w(?:arning)?/xms) { $w = parse_check( shift @argv ) } |
when (/^-?-c(?:ritical)?/xms) { $c = parse_check( shift @argv ) } |
when (/^-?-c(?:ritical)?/xms) { $c = parse_check( shift @argv ) } |
|
when (/^-?-u(?:nknown)?/xms) { |
|
$checks{_UNKNOWN} = { |
|
WARNING => $w, |
|
CRITICAL => $c, |
|
} |
|
} |
when (/^-?-n(?:eighbor)?/xms) { |
when (/^-?-n(?:eighbor)?/xms) { |
while ( @argv && $argv[0] !~ /^-/xms ) { |
while ( @argv && $argv[0] !~ /^-/xms ) { |
$checks{ shift @argv } = { |
$checks{ shift @argv } = { |
WARNING => $w, |
WARNING => $w, |
CRITICAL => $c |
CRITICAL => $c, |
} |
} |
} |
} |
} |
} |
|
|
sub print_help { |
sub print_help { |
print <<"EOL"; |
print <<"EOL"; |
$PROGNAME - checks status of OpenBGPd peers |
$PROGNAME - checks status of OpenBGPd peers |
$PROGNAME [ -w ENTRY ][ -c ENTRY ][ -n NEIGHBOR [ NEIGHBOR2 ] ] |
$PROGNAME [ -s SOCKET ][ -w ENTRY ][ -c ENTRY ]( -u | -n NEIGHBOR ) |
|
|
Usage: |
Usage: |
|
-s, --socket SOCKET |
|
Path to bgpd socket to use. See -r in bgpd(8). |
-w, --warning RANGE or single ENTRY |
-w, --warning RANGE or single ENTRY |
Exit with WARNING status if outside of RANGE or if != ENTRY |
Exit with WARNING status if outside of RANGE or if != ENTRY |
|
May be entered multiple times. |
-c, --critical RANGE or single ENTRY |
-c, --critical RANGE or single ENTRY |
Exit with CRITICAL status if outside of RANGE or if != ENTRY |
Exit with CRITICAL status if outside of RANGE or if != ENTRY |
|
May be entered multiple times. |
-n, --neighbor NEIGHBOR |
-n, --neighbor NEIGHBOR |
The name of the Neighbor |
The name of the Neighbor, can be a space separated list of neighbors. |
|
May be entered multiple times. |
|
-u, --unknown |
|
As if you specified -n for all unknown neighbors |
|
|
ENTRY is a comma separated list of items to match against. Each item can be |
ENTRY is a comma separated list of items to match against. Each item can be |
a RANGE or it will just be matched against the status. |
a RANGE or it will just be matched against the status. |
|
|
RANGE is specified as two optional numbers separated with a colon (:). The |
RANGE is specified as two optional numbers separated with a colon (:). The |
check is that the value is between the two numbers. If either number is left |
check is that the value is between the two numbers. If either number is left |
off, that check is ignored |
off, that check is ignored. |
|
|
|
If either number in a RANGE is specified as a percent, check is that |
|
max-prefix is specified and that the number is within the specified percent. |
|
|
NEIGHBOR is the name that shows when running "bgpctl show summary" |
NEIGHBOR is the name that shows when running "bgpctl show summary" |
|
|
Examples: |
Examples: |
|
|
the output causes a CRITICAL result. |
the output causes a CRITICAL result. |
|
|
Any time a NEIGHBOR that is NOT specified on the command line shows up in the |
Any time a NEIGHBOR that is NOT specified on the command line shows up in the |
output causes a CRITICAL result. |
output causes a CRITICAL result. If -u is specified, it treats NEIGHBOR as if |
|
it were specified at that position. |
|
|
|
|
$PROGNAME -w 10:300 -c 10:500 -n P1 P2 -n P3 |
|
|
|
CRITICAL |
|
If any of P1, P2, P3 are below 10, above 500 or any non-numeric value. |
|
|
|
WARNING |
|
If any of P1, P2, P3 are above 300. |
|
|
|
|
|
$PROGNAME -c Idle -n P1 -c 1:1 -n P2 -w 200:300 -c Active,10: -n P3 |
$PROGNAME -c Idle -n P1 -c 1:1 -n P2 -w 200:300 -c Active,10: -n P3 |
|
|
CRITICAL |
CRITICAL |
|
|
|
|
WARNING |
WARNING |
If P3 is above 10 and below 200 or above 300. |
If P3 is above 10 and below 200 or above 300. |
|
|
|
|
|
$PROGNAME -u -w 50%:70% -c 10%:90% -n P2 P3 |
|
|
|
No checks of unknown neighbors. |
|
|
|
CRITICAL |
|
If P2 or P3 do not have max-prefix set or if they do but learned prefixes |
|
are below 10% or above 90% of max-prefix or any non-numeric value. |
|
|
|
WARNING |
|
If P2 or P3 have learned prefixes below 50% or above 70% of max-prefix. |
|
|
|
|
|
$PROGNAME -w 50%:70% -c 10%:90% -u |
|
|
|
CRITICAL |
|
If any neighbor does not have max-prefix set or if they do but learned |
|
prefixes are below 10% or above 90% of max-prefix or any non-numeric value. |
|
|
|
WARNING |
|
If any neighbor have learned prefixes below 50% or above 70% of max-prefix. |
|
|
EOL |
EOL |
|
|