On Mon, Feb 06, 2006 at 01:53:58AM -0500, Ed Ravin wrote:
> Attached is my first try at an OSPF monitoring script meant for use in Mon.
> It's loosely based on bgp.monitor.
...
> The script will also tell you about addressless interfaces that have
> OSPF enabled - I need to put a bit more code in the script to identify
> them (currently you just see an ifIndex without explanation).

I started feeling guilty about not including that feature, so here's
an updated version that properly displays addressless interfaces, and
in addition fixes the --exclude option so the monitor is actually useful.

I'll drop this into the contrib directory after I've had some time to
shake it out and get feedback.

        -- Ed
#!/usr/bin/perl
#
# Router ospf (Open Shortest Path First) monitor
# Look at each router and get the status of all OSPF neighbors.
# Issue alarm if any interfaces configured for neighbors do not
#   have a full adjacencies
# Detail log shows status of all enabled OSPF interfaces.

# Usage:
#     ospf.monitor [--exclude pattern] [--community str] router1 [...]
#
# --exclude - don't alarm for IP addresses that match <pattern>.  Periods
# in the IP address will be escaped so that they only match periods.  Use
# [0-9] or the like if you need character class matching.  Use 'ip|ip|ip'
# to exclude multiple peers.
#
# --community - SNMPv1 community name to use.  But it's more secure
# to pass the community in via the environment variable COMMUNITY.


#
# Edit history below
# Version 0.1
# 
# By Ed Ravin <[EMAIL PROTECTED]>  This code is made available courtesy of
# PANIX http://www.panix.com.
# Copyright 2005, by Ed Ravin
#
# License: GNU GPL v2, see http://www.gnu.org/copyleft/gpl.html
#
# Loosely based on bgp.monitor which is:
#   Copyright 2002, by Marc Hauswirth, Safe Host SA <[EMAIL PROTECTED]>
#
# Some inspiration is taked from others mon monitors and from
# routerinfo.pl by Ben Buxton ([EMAIL PROTECTED]), also under GPL, see 
http://www.zipworld.com.au/~bb/linux/
# and from routerint.monitor by P. Strauss ([EMAIL PROTECTED]) and me self 
([EMAIL PROTECTED]).
#

# This script need the SNMP Session module from Simon Leinen <[EMAIL PROTECTED]>
#   Wich you could found under http://www.switch.ch/misc/leinen/snmp/perl/
#   It is also part of MRTG (http://people.ee.ethz.ch/~oetiker/webtools/mrtg/)

use SNMP;
use SNMP_Session;
use Getopt::Long;
use strict;

my %opt;

$opt{'community'}= undef;
$opt{'exclude'}= "";
$opt{'debug'}= undef;
my $usage="Usage: [COMMUNITY=str] ospf.monitor [--exclude regexp] [--community 
str] router [...]\n";
GetOptions(\%opt, "exclude=s", "community=s", "debug") or die $usage;

# It's highly unlikely someone wants dots in an IP address to be treated
# as a regexp pattern, so we'll escape them to make behavior more predictable.
# If you really want to use pattern matching, use a character class like
# [0-9] instead.
$opt{exclude} =~ s/\./\\./g;
$opt{exclude}= '^(' . $opt{exclude} . ')';
$opt{exclude}= "NOT_USED" if $opt{exclude} eq "^()";


## --
my $community = $opt{'community'} || $ENV{'COMMUNITY'} || "public";

## --

my @failures;
my @details;

$ENV{'MIBS'}= ""; # all OIDs needed are specified in script

# OID's to the SNMP elements that I want to show...
# From Cisco's MIB and RFC's
# http://sunsite.cnlab-switch.ch/ftp/doc/standard/rfc/16xx/1657
# http://www.telecomm.uh.edu/stats/rfc/BGP4-MIB.html

my %oids = ( 
        "SysUptime"                     =>      "1.3.6.1.2.1.1.3.0",
        "ifDescr"                       =>      "1.3.6.1.2.1.2.2.1.2",
        "ospfRouterId"                  =>      "1.3.6.1.2.1.14.1.1" ,
        "ospfIfIpAddress"               =>      "1.3.6.1.2.1.14.7.1.1" ,
        "ospfAddressLessIf"             =>      "1.3.6.1.2.1.14.7.1.2" ,
        "ospfIfAdminStat"               =>      "1.3.6.1.2.1.14.7.1.5" ,
        "ospfIfState"                   =>      "1.3.6.1.2.1.14.7.1.12" ,
        );


my %ospfIfStates = (
        1 => "down",
        2 => "loopback",
        3 => "waiting",
        4 => "pointToPoint",
        5 => "designatedRouter",
        6 => "backupDesignatedRouter",
        7 => "otherDesignatedRouter",
        );

my %ospfAdminStatus = (
        1 => "enabled",
        2 => "disabled",
        );


my %state;
my $router;

sub snmpget1 # session, oid-hashstr, instance
{
        my $session= shift;
        my $oidstr= shift;
        my $instance = shift;
        my $result= $session->get(".$oids{$oidstr}.$instance");

        if ($session->{ErrorNum})
        {
                push @failures, $router;
                push @details, "$router: error on SNMP get of 
$oidstr.$instance: $session->{ErrorStr}";
                return 0;
        }
        return $result;
}
foreach $router (@ARGV) {
        # Get some infos about this router
        my $sess = new SNMP::Session ( DestHost => $router, Community => 
$community );
        if (!defined($sess))
        {
                push @failures, $router;
                push @details, "$router: cannot create SNMP session";
                next;
        }
        
        my $ospfRouterID = snmpget1($sess, "ospfRouterId", "0") || next;
        
        push @details, "$router (Router-ID $ospfRouterID)";

        # Find the indexes of the interfaces with OSPF enabled
        my @ospfinterfaces;

        my $vars  = new SNMP::VarList([$oids{ospfIfAdminStat}]);
        for (my @vals = $sess->getnext($vars);
                        $vars->[0]->tag =~ /1\.3\.6\.1\.2\.1\.14\.7\.1\.5/      
 # still in table (Did you have a cleaner solutions ?)
                        and 
                        not $sess->{ErrorStr};          # and not end of mib or 
other error
                        @vals = $sess->getnext($vars))
                {
                        
                        my $textIfAdminStatus = $ospfAdminStatus{$vals[0]};
                        push  @ospfinterfaces, $vars->[0]->tag
                                if $textIfAdminStatus eq "enabled";
                }
        # trim down OID to keep just the interface part, which we will use
        # shortly as an instance ID
        map {s/^\.$oids{ospfIfAdminStat}\.//} @ospfinterfaces;

        foreach my $int (@ospfinterfaces)
        {
                my $ifstate = snmpget1($sess, "ospfIfState", "$int");
                my $ifinfo= $int; 
                if ($int =~ /0\.0\.0\.0\.(\d+)$/) {
                        my $ifindex= $1;
                        $ifinfo= snmpget1($sess, "ifDescr", $ifindex) . " 
(.$ifindex)";
                }
                push @details, sprintf("$router:  Interface %-23s  
%-15s",$ifinfo, $ospfIfStates{$ifstate}); 

                # if ospfIfState not in [4..7] (OSPF full adjacency states)
                if ($ifstate < 4 or $ifstate > 7) {
                        push @failures, $router unless $int =~ $opt{exclude} or 
grep(/$router/, @failures);
                        $details[$#details] .= "  [NO ADJACENCY]";
                }
        }
}

if (@failures) {
        print join(' ', @failures), "\n";
};
if (@details) {
        print "\n";
        print join("\n", @details), "\n";
}

if (@failures) {
        # Error state exit
        exit 1;
} else {
        # Correct exit
        exit 0;
};

_______________________________________________
mon mailing list
mon@linux.kernel.org
http://linux.kernel.org/mailman/listinfo/mon

Reply via email to