check_bird_ospf 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. #!/usr/bin/perl -W
  2. #
  3. # Maximilian Wilhelm <max@rfc2324.org>
  4. # -- Tue 04 Apr 2017 07:00:50 PM CEST
  5. #
  6. use strict;
  7. # Should we check the OSPF process for IPv4 or IPv6?
  8. my $cmds = {
  9. "-4" => "birdc",
  10. "-6" => "birdc6",
  11. };
  12. # Default to Legacy IP
  13. my $cmd = $cmds->{"-4"};
  14. if ($ARGV[0]) {
  15. unless (defined $cmds->{$ARGV[0]}) {
  16. print STDERR "Usage: $0 [ -4 | -6 ]\n";
  17. exit (1);
  18. }
  19. $cmd = $cmds->{$ARGV[0]};
  20. }
  21. my $code = 0;
  22. my $msg = "";
  23. if (not open (INTERFACES, "$cmd show ospf interface |")) {
  24. print "Failed to read OSPFv4 interfaces: $!\n";
  25. exit (2);
  26. }
  27. if (not open (NEIGHBORS, "$cmd show ospf neighbors |")) {
  28. print "Failed to read OSPFv4 neighbors: $!\n";
  29. exit (2);
  30. }
  31. # Store any configured OSPF interfaces
  32. my $interfaces = {};
  33. my $interface = undef;
  34. while (my $line = <INTERFACES>) {
  35. chomp ($line);
  36. # Create entry in interface hash
  37. if ($line =~ /^Interface (.+) \(/) {
  38. $interface = $1;
  39. $interfaces->{$interface} = {};
  40. }
  41. # Store Type and State attributes
  42. elsif ($line =~ m/(Type|State): (.+)$/) {
  43. $interfaces->{$interface}->{$1} = $2;
  44. }
  45. }
  46. close (INTERFACES);
  47. # Delete any stub interfaces from our list
  48. for my $iface (keys %{$interfaces}) {
  49. if ($interfaces->{$iface}->{State} =~ m/\(stub\)/) {
  50. delete $interfaces->{$iface};
  51. }
  52. }
  53. my @ok = ();
  54. my @broken = ();
  55. my @down = ();
  56. # Check all neighor states
  57. while (my $line = <NEIGHBORS>) {
  58. chomp ($line);
  59. if ($line =~ m@^([[:xdigit:].:]+)\s+(\d+)\s+([[:alnum:]/-]+)\s+([0-9:]+)\s+([[:alnum:]_.-]+)\s+([[:xdigit:].:]+)@) {
  60. my ($peer, $state, $ifname) = ($1, $3, $5);
  61. my $interface = $interfaces->{$ifname};
  62. # Mark interfaces as "up" in bird
  63. $interface->{up} = 1;
  64. # State FULL is awesome.
  65. if ($state =~ m@Full@) {
  66. push @ok, "$ifname/$peer";
  67. }
  68. # In broadcast areas there are only two FULL sessions (to the DR and BDR),
  69. # all other sessions will be 2-Way/Other which is perfectly fine.
  70. elsif ($state eq "2-Way/Other" and $interface->{Type} eq "broadcast") {
  71. push @ok, "$ifname/$peer";
  72. }
  73. # Everything else is considered broken.
  74. # Likely some ExStart/* etc. pointing to possible MTU troubles.
  75. else {
  76. push @broken, "$ifname/$peer:$state";
  77. }
  78. }
  79. }
  80. close (NEIGHBORS);
  81. # Check for any interfaces which should have (at least) an OSPF peer
  82. # but don't appear in the neighbors list
  83. for my $iface (keys %{$interfaces}) {
  84. if (not defined $interfaces->{$iface}->{up}) {
  85. push @down, $iface;
  86. }
  87. }
  88. # Any down interfaces?
  89. if (@down) {
  90. $code = 2;
  91. $msg .= "DOWN: " . join (', ', @down) . " ";
  92. }
  93. # Any broken sessions?
  94. if (@broken) {
  95. # Issue a warning when there are issues..
  96. if ($code < 2) {
  97. $code = 1
  98. }
  99. $msg .= "BROKEN: " . join (', ', @broken) . " ";
  100. }
  101. print $msg . "OK: " . join (', ', @ok) . "\n";
  102. exit ($code);