#    Big Sister network monitor
#    Copyright (C) 1998  Thomas Aeby
#
#    This program is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation; either version 2 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program; if not, write to the Free Software
#    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#

package rules;

# the procedure rules::config is called each time the file is read
sub config {
    my( $chk );
    my( $config ) = "$BigSister::common::fs{'adm'}";
    my( %hosttype ) = &hosttype;
    my( $host, @attr, $attr, $alias );
    my( $tcp, $bb, $procs, $sar, $rpc, $loc );

    undef $rules::ping;
    #load all the modules we'd like to use
    &uxmon::load_module( "tcp" );
    &uxmon::load_module( "bb" );
    &uxmon::load_module( "procs" );
    &uxmon::load_module( "fs" );
    &uxmon::load_module( "sar" );
    &uxmon::load_module( "rpc_ping" );
    &uxmon::load_module( "snmp" );
    &uxmon::load_module( "dumpdates" );

    if( -f "$config/grouping" ) {
	my( $name, $realname, $groups );
	open( IN, "<$config/grouping" );
	while( <IN> ) {
	    chomp;
	    next if( /^#/ );
	    next if( /^$/ );
	    $realname = "";
	    if( /\((.*)\)/ ) {
		$realname = $1;
		$_ = $`.$';
	    }
	    ($name,@groups) = split( /[\s\t]+/ );
	    if( $name eq "localhost" ) { $name = $uxmon::hostname;
	    &uxmon::join_group( $name, @groups ) if( @groups );
	    &uxmon::displayname( $name, $realname ) if( $realname );
	}
	close( IN );
	&uxmon::leave_on_exit(1);
    }
		
    #create a Monitor object watching sar output
    &uxmon::checker(
	$sar = Monitor::sar->new
    );
    $sar->add_check( "%idle", undef, undef, 15 );
    $sar->add_check( "%wio", undef, undef, undef, 50, undef );
    $sar->add_check( "freeswap", undef, 20000, 60000 );
    $sar->add_check( "%busy", $uxmon::hostname.".disk", undef, undef, 40, 80 );

    #create a Monitor object watching tcp ports
    &uxmon::checker(
	$tcp = Monitor::tcp->new( 8 )
    );

    # read config from uxmon-net if present
    if( -f "$config/uxmon-net" ) {
	open( _IN, "<$config/uxmon-net" );
	while( <_IN> ) {
	    chomp;
	    ($host, @attr) = split( /[\s\t]+/ );
	    $alias = $host;
	    if( $host =~ /^(.*)\((.*)\)/ ) {
		$host = $1;
		$alias = $2;
	    }
	    undef $rpc;
	    foreach $attr (@attr) {
		if( $attr eq "ping" ) {
		    add_ping( $host, "$alias.conn" );
		}
		elsif( grep( $_ eq $attr, "smtp", "pop3", "nntp", "printer" ) ) {
		    $tcp->add_any( $host, $attr, "$alias.$attr" );
		}
		elsif( $attr eq "nfs" ) {
		    &uxmon::checker(
			$rpc = Monitor::rpc_ping->new( 1 )
		    ) unless( $rpc );
		    $rpc->add_host( "$host.rpc", "$host", "mount", 1, "udp" );
		    $rpc->add_host( "$host.rpc", "$host", "nfs", 2, "udp" );
		}
		elsif( $attr eq "nlm" ) {
		    &uxmon::checker(
			$rpc = Monitor::rpc_ping->new( 1 )
		    ) unless( $rpc );
		    $rpc->add_host( "$host.rpc", "$host", "nlm", 2, "udp" );
		}
		elsif( $attr =~ /^http(.*)/ ) {
		    my( $port, $url ) = ( "http", "/" );
		    if( $attr =~ /:(\d+)/) {
			$port = $rules::1;
			$attr =~ s/:\d+//;
		    }
		    if( $attr =~ /:/ ) {
			$url = $attr;
		    }
		    $tcp->add_any( $host, "http", "$alias.http", $url, $port );
		}
		elsif( grep( $attr eq $_, "novell", "nt", "cds", "caty", "hub", "notes" ) ) {
		    &snmp( $host, $attr );
		}
		else {
		    $tcp->add_any( "$host", $attr, "$alias.$attr" );
		}
	    }
	}
        close _IN;
    }
    else {
	$tcp->add_any( $uxmon::hostname, "smtp" );
	$tcp->add_any( $uxmon::hostname, "printer" ) if( $hosttype{"LPD"} );
	$tcp->add_any( $uxmon::hostname, "pop3" ) if( $hosttype{"POP"} );
	$tcp->add_any( $uxmon::hostname, "smb" ) if( $hosttype{"PCS"} );
    }

    &uxmon::checker(
	$proc = Monitor::procs->new
    );
    $proc->add_check( "nfsd", undef, 1, 16 ) if( $hosttype{"nfsserver"} );
    $proc->add_check( "lockd", undef, 1, 16 ) if( $hosttype{"nfsserver"} );
    $proc->add_check( "mountd", undef, 1, 16 ) if( $hosttype{"nfsserver"} );
    $proc->add_check( "hclnfsd", undef, 1, 1 ) if( $hosttype{"PCS"} );
    $proc->add_check( "rpc.pcnfsd", undef, 1, 1 ) if( $hosttype{"PCS"} );
    $proc->add_check( "sendmail", undef, 1, 30 );
    $proc->add_check( "lpd", undef, 1, 30 ) if( $hosttype{"LPD"} );
    $proc->add_check( "dhcpd", undef, 1, 2 ) if( $hosttype{"dhcp"} );
    $proc->add_check( "ypbind", undef, 1 ) if( $hosttype{"yp"} );
    $proc->add_check( "ypserv", undef, 1 ) if( $hosttype{"ypserver"} );
    $proc->add_check( "ypxfrd", undef, 1 ) if( $hosttype{"ypmaster"} );

    &uxmon::checker(
	$fs = Monitor::fs->new
    );
    $fs->add_check( "/", $uxmon::hostname.".disk", 2000, 1000 ) if( $hosttype{"PCS"} || $hosttype{"oracle"} || $hosttype{"LPD"} || $hosttype{"POP"} );
    $fs->add_check( "/usr", $uxmon::hostname.".disk", 8000, 4000 ) if( ($hosttype{"PCS"} || $hosttype{"oracle"})  && ! $hosttype{"test"} );
    $fs->add_check( "/var", $uxmon::hostname.".disk", 20000, 10000 ) if( ($hosttype{"PCS"} || $hosttype{"oracle"} || $hosttype{"LPD"} || $hosttype{"POP"}) && $hosttype{"have_var"} );
    $fs->add_check( "/oracle", $uxmon::hostname.".disk", 120000, 60000 ) if( $hosttype{"oracle"} );
    $fs->add_check( "/oracle/db/dat", $uxmon::hostname.".disk", 120000, 60000 ) if( $hosttype{"oracle"} && -d "/oracle/db/dat" );

    &uxmon::checker(
	$rpc = Monitor::rpc_ping->new( 1 )
    );
    $rpc->add_host( "$uxmon::hostname.rpc", "localhost", "mount", 1, "udp" ) if( $hosttype{"nfsserver"} );
    $rpc->add_host( "$uxmon::hostname.rpc", "localhost", "nfs", 2, "udp" ) if( $hosttype{"nfsserver"} );
    $rpc->add_host( "$uxmon::hostname.rpc", "localhost", "nlm", 2, "udp" ) if( $hosttype{"nfsserver"} );
    $rpc->add_host( "$uxmon::hostname.rpc", "localhost", "yp", 2, "udp" ) if( $hosttype{"ypserver"} );
    $rpc->add_host( "$uxmon::hostname.rpc", "localhost", "yppasswd", 1, "udp" ) if( $hosttype{"ypmaster"} );

    if( $hosttype{"PCS"} ) {
	$loc = substr( $uxmon::hostname, 0, 3 );
	&add_ping( $loc."notes" ) if( gethostbyname( $loc."notes" ) );
	&snmp( $loc."notes", "notes" ) if( gethostbyname( $loc."notes" ) );
	if( gethostbyname( $loc."cd" ) ) {
#	    &add_ping( $loc."cd" );
	    $rpc->add_host( "${loc}cd.rpc", "${loc}cd", "mount", 1, "udp" );
#	    $tcp->add_any( "${loc}cd", "smb" );
	    &snmp( "${loc}cd", "cds" );
	}
    }

    # if dump is used for backup warn if last level 7 backup
    # is more than 3 days or last level 0 backup is more than 30 days old
    if( $hosttype{"dumpbak"} ) {
	&uxmon::checker(
	    $chk = Monitor::dumpdates->new
	);
	$chk->add_check(undef, 7, undef, "dump days", 4.5*24*3600, 6*24*3600 );
	$chk->add_check(undef, 0, undef, "dump days", 30*24*3600, 37*24*3600 );
    }

#    &uxmon::checker(
#	$snmp = Monitor::snmp->new( "solarix", "public" )
#    );
#    $snmp->add_check( "ifOutUcastPkts.2", undef, "ifOutUcastPkts", 1, undef, undef, 5, 10 );
#    $snmp->add_check( "sysLocation.0", undef, "Location", undef, "Home", undef, undef, "Home" );
    
    # create a reporter reporting to host "obelix"
    &uxmon::reporter(
	$bb = Monitor::bb->new( "obelix" )
    );

}


sub hosttype {
    my( %hosttype, $domain );
    my( $mtime );

    chomp( $domain = `domainname 2>/dev/null` );
    $hosttype{"yp"} = $domain;
    $hosttype{"ypserver"} = $domain && -d "/var/yp/$domain";
    $hosttype{"ypmaster"} = `ypwhich -m passwd` =~ /^$uxmon::hostname[\r\n]*$/; # ah, well ....
    $hosttype{"PCS"} = -d "/pcs/infra";
    $hosttype{"POP"} = (($uxmon::hostname =~ /^pop/) || $hosttype{"PCS"}) ;
    $hosttype{"LPD"} = ((-f "/etc/printcap") || $hosttype{"PCS"}) ;
    system( "grep -s nfs /etc/dfs/sharetab > /dev/null 2>&1" );
    $hosttype{"nfsserver"} = (! $?) || (-f "/etc/exports" );
    $hosttype{"dhcp"} = (-f "/etc/dhcpd.conf");
    $hosttype{"oracle"} = (-f "/l/adm/orainstance");
    $hosttype{"test"} = ( $uxmon::hostname eq "beatnix" );
    my $df = `df`;
    $hosttype{"have_var"} = ($df =~ /\/var[\s\t]/);
    if( -f "/etc/dumpdates" ) {
	$mtime = (stat(_))[9];
	if( time-$mtime<3600*24*60 ) {
	    $hosttype{"dumpbak"} = 1;
	}
    }
    if( $BigSister::common::dl > 4 ) {
	print STDERR "host type:\n";
	my( $name, $val );
	while( ($name,$val) = each %hosttype ) {
	    print STDERR "  $name: $val\n";
	}
    }

    return %hosttype;
}


sub add_ping {
    my( $host, $item ) = @_;

    $item = $host.".conn" unless( $item );
    unless( $rules::ping ) {
	&uxmon::load_module( "ping" );
	&uxmon::checker(
	    $rules::ping = Monitor::ping->new( "udp", 8 )
	);
    }
    $rules::ping->add_hosts( $host, $item );
}



sub snmp {
    my( $host, $type ) = @_;
    my( $snmp, %snmp_types, $i );

    %snmp_types = ( "novell", ":novell:net:storage:cpu:nwusers:ping:",
		    "nt", ":nt:net:ping:", 
		    "caty", ":caty:hub:ping:", 
		    "hub", ":hub:ping:", 
		    "cds", ":cds:net:ping:",
		    "notes", ":net:ping:");
    my %community = ( "notes", "AscomCH" );
    my $community = $community{$type};
    $community = "public" unless( $community );
    $type = $snmp_types{$type};
    &uxmon::checker(
	$snmp = Monitor::snmp->new( $host, $community )
    );
    if( $type =~ /:ping:/ ) {
	$snmp->poll_fail( "$host.conn" );
    }
    if( $type =~ /:(net|hub):/ ) {
	my( $iface, $speed );
	my( @ifaces ) = $snmp->walk( "ifDescr" );
	$i = 0;
	foreach $iface (@ifaces) {
	    $iface =~ s/:.*//;
	    if( $type =~ /:hub:/ ) {
		$snmp->add_check( "ifInErrors.$iface", "$host.net", "IE.$iface", "PERSEC", undef, undef, 2, 6 ) if( $snmp->get("ifInErrors.$iface"));
		$snmp->add_check( "ifOutErrors.$iface", "$host.net", "OE.$iface", "PERSEC", undef, undef, 2, 6 ) if( $snmp->get("ifOutErrors.$iface"));
	    }
	    else {
		$snmp->add_check( "ifOperStatus.$iface", "$host.net", "Up.$iface", undef, 1 );
		$snmp->add_check( "ifInErrors.$iface", "$host.net", "InErrors.$iface", "PERSEC", undef, undef, 2, 6 );
		$snmp->add_check( "ifOutErrors.$iface", "$host.net", "OutErrors.$iface", "PERSEC", undef, undef, 2, 6 );
	    }
	}
	if( $type =~ /:storage:/ ) {
	    my( @ids ) = $snmp->walk( "hrStorageIndex" );
	    my( $sdescr, $ssize, $stype );

	    foreach $id (@ids) {
		$id =~ s/.*://;
	        $sdescr = (($snmp->get( "hrStorageDescr.$id" ))[0]);
	        $ssize = (($snmp->get( "hrStorageSize.$id" ))[0]);
	        $stype = (($snmp->get( "hrStorageType.$id" ) )[0]);
		if( $type =~ /:novell:/ ) {
		    # watch disks and Alloc Memory Pool
		    if( $stype =~ /\.1$/ ) {
			$snmp->add_check( "hrStorageUsed.$id", "$host.disk", "$sdescr($ssize)", undef, undef, undef, $ssize*($sdescr=~/SYS:/?0.98:0.9), $ssize*0.99 );
		    }
		    elsif( $stype =~ /\.3$/ ) {
			$snmp->add_check( "hrStorageUsed.$id", "$host.cpu", "$sdescr($ssize)", undef, undef, undef, $ssize*0.9, $ssize*0.99 );
		    }
		}
	    }
	}
	if( $type =~ /:cpu:/ ) {
	    my( @load ) = $snmp->walk( "hrProcessorLoad" );
	    my( $load );

	    foreach $load (@load) {
		$load =~ s/:.*//;
		$snmp->add_check( "hrProcessorLoad.$load", "$host.cpu", "%cpu", undef, undef, undef, 80, undef );
	    }
	}
	if( $type =~ /:nwusers:/ ) {
	    my( @uinfo );

	    @uinfo = $snmp->get( "nwMaxLogins.0" );
	    if( @uinfo ) {
		$snmp->add_check( "nwLoginCount.0", "$host.cpu", "logged in users(max: ".$uinfo[0].")", undef,undef, undef, $uinfo[0]-10, $uinfo[0]-2 );
	    }
	}
    }
}


1;
