From b516027c1b6e2aa9600b02e4a35f7e2ad05c8fe1 Mon Sep 17 00:00:00 2001 From: Simon Ruderich Date: Sat, 30 Dec 2023 09:28:40 +0100 Subject: [PATCH] icinga/check_bird: add --- README.adoc | 9 +++++ icinga/check_bird | 98 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+) create mode 100644 README.adoc create mode 100755 icinga/check_bird diff --git a/README.adoc b/README.adoc new file mode 100644 index 0000000..dfb87b4 --- /dev/null +++ b/README.adoc @@ -0,0 +1,9 @@ += README + +Repository of miscellaneous tools which might be useful to others. They are +licensed under GPLv3+ except where otherwise noted. + +:bird: https://bird.network.cz/ + +- icinga/check_bird: Connect to {bird}[BIRD] and check if a given list of + protocols is running. diff --git a/icinga/check_bird b/icinga/check_bird new file mode 100755 index 0000000..999bd1c --- /dev/null +++ b/icinga/check_bird @@ -0,0 +1,98 @@ +#!/usr/bin/perl + +# Simple Nagios-compatible checker for BIRD protocols. + +# SPDX-License-Identifier: GPL-3.0-or-later +# Copyright (C) 2016-2023 Simon Ruderich + + +use strict; +use warnings; +use autodie; + +use Monitoring::Plugin; +use IO::Socket::UNIX (); + + +my $np = Monitoring::Plugin->new( + usage => "usage: %s [-s ] ..", +); +$np->add_arg( + spec => 'socket|s=s', + help => 'Path to bird UNIX control socket.', + default => '/run/bird/bird.ctl', +); +$np->getopts; + +if (@ARGV == 0) { + $np->plugin_exit(OK, 'no protocols specified'); +} + +alarm $np->opts->timeout; # handler already set by Monitoring::Plugin + + +my $bird = IO::Socket::UNIX->new( + Type => IO::Socket::UNIX::SOCK_STREAM, + Peer => $np->opts->socket, +) or $np->plugin_exit(CRITICAL, "failed to open '" . $np->opts->socket . "'"); + +$_ = <$bird> // $np->plugin_exit(CRITICAL, 'failed to read hello'); +/^0001 / or $np->plugin_exit(CRITICAL, 'invalid hello'); + + +sub bird_command { + my ($cmd) = @_; + + $bird->send("$cmd\n") + // $np->plugin_exit(CRITICAL, "failed to send command '$cmd'"); + + my @result; + while (<$bird>) { + next if /^\+/; # ignore spontaneous printout + chomp; + + if (/^8/ or /^9/) { + $np->plugin_exit(CRITICAL, + "error while running command '$cmd': $_"); + } + + push @result, $_; + return @result if /^\d{4} /; + } + $np->plugin_exit(CRITICAL, "incomplete output for command '$cmd'"); +} + +foreach my $name (@ARGV) { + foreach (bird_command("show protocols $name")) { + next unless /^1002-/; + s/\s+$//; + + my @data = split /\s+/, $_, 6; + + my $proto = $data[1]; + my $status = $data[3]; + my $info = $data[5] // ''; + # Hacky workaround for "timeformat protocol iso long" + $info =~ s/^\d{2}:\d{2}:\d{2}\s+//; + + # Administratively disabled. + if ($status ne 'up') { + $np->add_message(CRITICAL, "protocol '$name' not up"); + } + # Not running. + my $failed = 0; + if ($proto eq 'BGP') { + $failed = 1 if $info ne 'Established'; + } elsif ($proto eq 'OSPF') { + $failed = 1 if $info ne 'Running'; + } else { + $np->add_message(WARNING, "unknown protocol '$proto', " + . 'please file a bug report'); + } + if ($failed) { + $np->add_message(CRITICAL, "protocol '$name' not running: '$info'"); + } + } +} + +$np->plugin_exit($np->check_messages(join => ', ')); -- 2.45.2