]> ruderich.org/simon Gitweb - misc/misc.git/commitdiff
icinga/check_bird: add
authorSimon Ruderich <simon@ruderich.org>
Sat, 30 Dec 2023 08:28:40 +0000 (09:28 +0100)
committerSimon Ruderich <simon@ruderich.org>
Sat, 30 Dec 2023 08:28:40 +0000 (09:28 +0100)
README.adoc [new file with mode: 0644]
icinga/check_bird [new file with mode: 0755]

diff --git a/README.adoc b/README.adoc
new file mode 100644 (file)
index 0000000..dfb87b4
--- /dev/null
@@ -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 (executable)
index 0000000..999bd1c
--- /dev/null
@@ -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 <socket>] <proto>..",
+);
+$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 => ', '));