]> ruderich.org/simon Gitweb - misc/misc.git/blob - icinga/check_bird
icinga/check_bird: add
[misc/misc.git] / icinga / check_bird
1 #!/usr/bin/perl
2
3 # Simple Nagios-compatible checker for BIRD protocols.
4
5 # SPDX-License-Identifier: GPL-3.0-or-later
6 # Copyright (C) 2016-2023  Simon Ruderich
7
8
9 use strict;
10 use warnings;
11 use autodie;
12
13 use Monitoring::Plugin;
14 use IO::Socket::UNIX ();
15
16
17 my $np = Monitoring::Plugin->new(
18     usage => "usage: %s [-s <socket>] <proto>..",
19 );
20 $np->add_arg(
21     spec    => 'socket|s=s',
22     help    => 'Path to bird UNIX control socket.',
23     default => '/run/bird/bird.ctl',
24 );
25 $np->getopts;
26
27 if (@ARGV == 0) {
28     $np->plugin_exit(OK, 'no protocols specified');
29 }
30
31 alarm $np->opts->timeout; # handler already set by Monitoring::Plugin
32
33
34 my $bird = IO::Socket::UNIX->new(
35     Type => IO::Socket::UNIX::SOCK_STREAM,
36     Peer => $np->opts->socket,
37 ) or $np->plugin_exit(CRITICAL, "failed to open '" . $np->opts->socket . "'");
38
39 $_ = <$bird> // $np->plugin_exit(CRITICAL, 'failed to read hello');
40 /^0001 /     or $np->plugin_exit(CRITICAL, 'invalid hello');
41
42
43 sub bird_command {
44     my ($cmd) = @_;
45
46     $bird->send("$cmd\n")
47         // $np->plugin_exit(CRITICAL, "failed to send command '$cmd'");
48
49     my @result;
50     while (<$bird>) {
51         next if /^\+/; # ignore spontaneous printout
52         chomp;
53
54         if (/^8/ or /^9/) {
55             $np->plugin_exit(CRITICAL,
56                              "error while running command '$cmd': $_");
57         }
58
59         push @result, $_;
60         return @result if /^\d{4} /;
61     }
62     $np->plugin_exit(CRITICAL, "incomplete output for command '$cmd'");
63 }
64
65 foreach my $name (@ARGV) {
66     foreach (bird_command("show protocols $name")) {
67         next unless /^1002-/;
68         s/\s+$//;
69
70         my @data = split /\s+/, $_, 6;
71
72         my $proto  = $data[1];
73         my $status = $data[3];
74         my $info   = $data[5] // '';
75         # Hacky workaround for "timeformat protocol iso long"
76         $info =~ s/^\d{2}:\d{2}:\d{2}\s+//;
77
78         # Administratively disabled.
79         if ($status ne 'up') {
80             $np->add_message(CRITICAL, "protocol '$name' not up");
81         }
82         # Not running.
83         my $failed = 0;
84         if ($proto eq 'BGP') {
85             $failed = 1 if $info ne 'Established';
86         } elsif ($proto eq 'OSPF') {
87             $failed = 1 if $info ne 'Running';
88         } else {
89             $np->add_message(WARNING, "unknown protocol '$proto', "
90                                     . 'please file a bug report');
91         }
92         if ($failed) {
93             $np->add_message(CRITICAL, "protocol '$name' not running: '$info'");
94         }
95     }
96 }
97
98 $np->plugin_exit($np->check_messages(join => ', '));