Search
j0ke.net Open Build Service
>
Projects
>
server:monitoring
:
icinga
:
production
>
nagios-plugins-iu
> check_bgp_new.pl
Sign Up
|
Log In
Username
Password
Cancel
Overview
Repositories
Revisions
Requests
Users
Advanced
Attributes
Meta
File check_bgp_new.pl of Package nagios-plugins-iu
#!/usr/bin/perl -w # # This Nagios plugin checks BGP sessions on a router. It checks that # the BGP sessions in a given list are in "established" state, and on # Juniper routers it can check that the number of prefixes learned # from each BGP neighbor falls within a given range. # # This is a rewrite of the Nagios plugin named check_bgp.pl, available # at SourceForge under the project named "IU Nagios Plugins". That # plugin checks that BGP sessions are in "established" state. This # plugin does the same, but allows passing in an optional set of # threshold values with each BGP neighbor. When the optional # thresholds are supplied on the command line, this plugin checks the # number of prefixes learned via each BGP session against the # thresholds. # # TODO: # Make it check prefixes on Cisco as well as Juniper routers. # # HISTORY: # version 2.0, 2006-08-09, named check_bgp_new.pl # Pete Siemsen, [EMAIL PROTECTED] # version 1.0, 2005-10-11, named check_bgp.pl # see SourceForge project "IU Nagios Plugins" use strict; use Getopt::Std; use Net::SNMP qw(:snmp); #use Data::Dumper; # debugging use vars qw/ %opt /; my $lastScriptModification = '2006-08-09'; # Standard Nagios plug-in return codes. my $NAGIOS_OK = 0; # success my $NAGIOS_WARNING = 1; # something is a little bit wrong my $NAGIOS_CRITICAL = 2; # something is very wrong my $NAGIOS_UNKNOWN = 3; # bad command-line arguments #============================================================================= # Do SNMP with the router and set %NeighborStatusTable. sub GetNeighborStatusTable($$$) { my $RouterName = shift; my $community = shift; my $NeighborStatusTableRef = shift; # Open an SNMPv2 session with the router my ($Session, $Error) = Net::SNMP->session( -version => 'snmpv2c', -timeout => 2, -hostname => $RouterName, -community => $community ); return $Error if !defined($Session); my $BaseOid = '1.3.6.1.2.1.15.3.1.2'; my $Result = $Session->get_table($BaseOid); if (!defined($Result)) { $Session->close; return $Session->error(); } foreach (keys %$Result) { my $newkey = $_; $newkey =~ s/^$BaseOid\.//; $$NeighborStatusTableRef{$newkey} = $$Result{$_}; } return 'success'; } #============================================================================= # Do SNMP with the router and set %NeighborReceivedPrefixTable. sub GetNeighborPrefixCounts($$$$) { my $RouterName = shift; my $community = shift; my $GetActiveCounts = shift; my $NeighborPrefixCountsRef = shift; # Open an SNMPv2 session with the router my ($Session, $Error) = Net::SNMP->session( -version => 'snmpv2c', -timeout => 2, -hostname => $RouterName, -community => $community ); return $Error if !defined($Session); # .iso.org.dod.internet.private.enterprises.juniperMIB. # jnxExperiment.jnkBGPM2Experiment.jnxBgpM2.jnxBgpM2Peer. # jnxBgpM2PeerData.jnxBgpM2PeerTable.jnxBgpM2PeerEntry. # jnxBgpMpPeerIndex my $jnxBgpMpPeerIndexOid = '1.3.6.1.4.1.2636.5.1.1.2.1.1.1.14'; my $SnmpPeerIndices = $Session->get_table($jnxBgpMpPeerIndexOid); if (!defined($SnmpPeerIndices)) { $Session->close; return $Session->error(); } # print Dumper $SnmpPeerIndices; my %PeerIndexToIp; foreach my $ReturnedOid (keys %$SnmpPeerIndices) { my $LocalOid = $ReturnedOid; $LocalOid =~ s/^$jnxBgpMpPeerIndexOid\.//; # remove the baseoid from the left next if $LocalOid !~ /^0\.1\./; # skip any non-ipv4 entries $LocalOid =~ /(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$)/; # get the IP address from the right $PeerIndexToIp{$$SnmpPeerIndices{$ReturnedOid}} = $1; } # print Dumper \%PeerIndexToIp; my $BaseOid; if ($GetActiveCounts) { # .iso.org.dod.internet.private.enterprises.juniperMIB. # jnxExperiment.jnkBGPM2Experiment.jnxBgpM2.jnxBgpM2Peer. # jnxBgpM2PeerCounters.jnxBgpM2PrefixCountersTable. # jnxBgpM2PrefixCountersEntry.jnxBgpM2PrefixInPrefixesAccepted $BaseOid = '1.3.6.1.4.1.2636.5.1.1.2.6.2.1.8'; } else { # .iso.org.dod.internet.private.enterprises.juniperMIB. # jnxExperiment.jnkBGPM2Experiment.jnxBgpM2.jnxBgpM2Peer. # jnxBgpM2PeerCounters.jnxBgpM2PrefixCountersTable. # jnxBgpM2PrefixCountersEntry.jnxBgpM2PrefixInPrefixes $BaseOid = '1.3.6.1.4.1.2636.5.1.1.2.6.2.1.7'; } my $SnmpPrefixCounts = $Session->get_table($BaseOid); if (!defined($SnmpPrefixCounts)) { $Session->close; return $Session->error(); } # print Dumper $SnmpPrefixCounts; foreach my $ReturnedOid (keys %$SnmpPrefixCounts) { my $LocalOid = $ReturnedOid; $LocalOid =~ s/^$BaseOid\.//; # remove the baseoid my ($PeerIndex, $Protocol, $RoutingTable) = split /\./, $LocalOid; next if $Protocol != 1; # skip non-ipv4 entries next if $RoutingTable != 1; # skip non-inet0 entries my $ip = $PeerIndexToIp{$PeerIndex}; $$NeighborPrefixCountsRef{$ip} = $$SnmpPrefixCounts{$ReturnedOid}; } # print Dumper $NeighborPrefixCountsRef; return 'success'; } # # Parse the "-n" command-line argument. Return an array of hashes # containing one hash for each neighbor. # sub ParseNeighborsArg ($$) { my $NeighborsArg = shift; my $LimitsMustBeCheckedRef = shift; my @Neighbors; my $Index = -1; foreach my $NeighborArg (split(',', $NeighborsArg)) { my ($ip, $name, $arg3, $arg4) = split('\%', $NeighborArg); $Index++; $Neighbors[$Index] = {}; # create a new anonymous hash for the neighbor $Neighbors[$Index]{Ip} = $ip; if ($ip !~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/) { print "INVALID COMMAND ARGUMENT - $ip isn't standard dotted-decimal notation\n"; exit $NAGIOS_UNKNOWN; } $Neighbors[$Index]{Name} = $name; my $PercentCount = ($NeighborArg =~ tr/%/%/); next if $PercentCount == 0; if ($PercentCount > 3) { print "INVALID COMMAND ARGUMENT - too many percent signs after $ip\n"; exit $NAGIOS_UNKNOWN; } $$LimitsMustBeCheckedRef = 1 if $PercentCount > 1; if (defined $arg4) { if ($arg3 >= $arg4) { print "INVALID COMMAND ARGUMENT - lower bound must be < upper bound for $ip \n"; exit $NAGIOS_UNKNOWN; } $Neighbors[$Index]{MinimumPrefixes} = $arg3; $Neighbors[$Index]{MaximumPrefixes} = $arg4; } elsif (defined $arg3) { $Neighbors[$Index]{PrefixCount} = $arg3; } } return @Neighbors; } #============================================================================= # Main. my $Usage = <<"EOF"; usage: $0 [-h] -r <hostname> -c <community> -n <neighbors> [-v] [-h] : Display this message and exit [-r] <router> : IP address or DNS name of the router [-c] <community>: SNMP community string (default = "public") [-n] <neighbors>: A comma-separated list of BGP neighbors, where each neighbor is an IP address followed by optional %-delimited values. The first value is a name for the neighbor, which is used to clarify the text messages generated by this script. The remaining one or two values, if they exist, have meaning only when the -r option specifies a Juniper router. They define limits on the number of prefixes that the router is learning from the BGP neighbor. If there is only one value, it defines the exact number of prefixes expected from the BGP neighber. If there are two values, they define lower and upper bounds on the number of prefixes expected from the neighbor. Examples: 10.10.10.1,10.10.20.2%ROUTER_B 1.2.3.4%PEER1%3,1.2.3.5%ISP1%100000%200000 [-a] : Has meaning only when the -r option specifies a Juniper router. When -a is specified, this plugin checks the number of active (used) routes instead of the number of received routes. When you check received routes, you're verifying that a BGP neighbor is sending you the number of routes that you expect. You might check received routes to verify that a neighbor hasn't screwed up a BGP filter. When you check active routes, you're verifying that the router is actually using the number of routes that you expect. You might check active routes to verify that most of your traffic is going out a primary link and not a backup link. This Nagios plugin uses SNMP to query a router about its BGP sessions. The -n argument defines the list of BGP sessions to be checked; other BGP sessions on the router will be ignored. If any of the listed BGP sessions is not in "established" state, or if a BGP neighbor isn't sending the expected number of prefixes, this plugin will return a non-success status. This Nagios plugin can check the existence of BGP sessions on any router that supports the standard BGP SNMP MIB. It can check prefix limits only on Juniper routers, since prefix counts are available only in a proprietary SNMP MIB that is implemented only by Juniper routers. On other routers, this script checks only whether BGP sessions are in "established" state. In other words, if you use this script to check BGP sessions on a non-Juniper router, don't try to specify any limits or you'll get an error. $lastScriptModification EOF if (!getopts('har:c:n:', \%opt) or (!exists $opt{r}) or (!exists $opt{n}) or (exists $opt{h})) { warn $Usage; exit $NAGIOS_UNKNOWN; } my $RouterName = $opt{r}; my $Community = (exists $opt{c}) ? $opt{c} : "public"; my $CheckActive = (exists $opt{a}) ? $opt{a} : 0; my $LimitsMustBeChecked = 0; my @ExpectedNeighbors = ParseNeighborsArg($opt{n}, \$LimitsMustBeChecked); #print Dumper @ExpectedNeighbors; my %NeighborStatusTable; my $status = GetNeighborStatusTable($RouterName, $Community, \%NeighborStatusTable); if ($status ne 'success') { print "SNMP ERROR - couldn't get BGP table from $RouterName\n"; exit $NAGIOS_CRITICAL; } #print Dumper \%NeighborStatusTable; my %BgpStates = ( "1" => "Idle", "2" => "Connect", "3" => "Active", "4" => "OpenSent", "5" => "OpenConfirm", "6" => "Established" ); # Check that all sessions are established. Exit if any aren't. my $BGP_ESTABLISHED = 6; my $UnestablishedNeighbors = ''; foreach my $ExpectedNeighbor (@ExpectedNeighbors) { my $ExpectedNeighborIp = $$ExpectedNeighbor{Ip}; if (!exists $NeighborStatusTable{$ExpectedNeighborIp}) { print "SNMP ERROR - BGP with $ExpectedNeighborIp is not configured on $RouterName\n"; exit $NAGIOS_CRITICAL; } my $SessionState = $NeighborStatusTable{$ExpectedNeighborIp}; if ($SessionState ne $BGP_ESTABLISHED) { my $ExpectedNeighborName = ($$ExpectedNeighbor{Name} eq '') ? $ExpectedNeighborIp : $$ExpectedNeighbor{Name}; $UnestablishedNeighbors .= " $ExpectedNeighborName"; } } if ($UnestablishedNeighbors ne '') { print "UNESTABLISHED BGP SESSIONS -$UnestablishedNeighbors\n"; exit $NAGIOS_CRITICAL; } if (!$LimitsMustBeChecked) { print "BGP OK - all sessions established\n"; exit $NAGIOS_OK; } my %NeighborPrefixCounts; $status = GetNeighborPrefixCounts($RouterName, $Community, $CheckActive, \%NeighborPrefixCounts); if ($status ne 'success') { print "SNMP ERROR - couldn't get prefix count table from $RouterName\n"; exit $NAGIOS_CRITICAL; } #print Dumper \%NeighborPrefixCounts; my $CountType = $CheckActive ? 'active' : 'received'; foreach my $ExpectedNeighbor (@ExpectedNeighbors) { my $ExpectedNeighborIp = $$ExpectedNeighbor{Ip}; my $ExpectedNeighborName = ($$ExpectedNeighbor{Name} eq '') ? $ExpectedNeighborIp : $$ExpectedNeighbor{Name}; my $ActualPrefixCount = $NeighborPrefixCounts{$ExpectedNeighborIp}; if (exists $$ExpectedNeighbor{PrefixCount}) { my $ExpectedPrefixCount = $$ExpectedNeighbor{PrefixCount}; if ($ActualPrefixCount != $ExpectedPrefixCount) { print "PREFIX COUNT WRONG - getting $ActualPrefixCount $CountType prefixes, expecting $ExpectedPrefixCount from neighbor $ExpectedNeighborName at ($ExpectedNeighborIp)\n"; exit $NAGIOS_WARNING; } } elsif (exists $$ExpectedNeighbor{MinimumPrefixes}) { my $Minimum = $$ExpectedNeighbor{MinimumPrefixes}; if ($ActualPrefixCount < $Minimum) { print "LOW BGP PREFIX COUNT - $ActualPrefixCount prefixes $CountType, minimum is $Minimum for neighbor $ExpectedNeighborName at ($ExpectedNeighborIp)\n"; exit $NAGIOS_WARNING; } my $Maximum = $$ExpectedNeighbor{MaximumPrefixes}; if ($ActualPrefixCount > $Maximum) { print "HIGH BGP PREFIX COUNT - $ActualPrefixCount prefixes $CountType, maximum is $Maximum for neighbor $ExpectedNeighborName at ($ExpectedNeighborIp)\n"; exit $NAGIOS_WARNING; } } } print "BGP OK - all sessions established\n"; exit $NAGIOS_OK;