Plugin:check rpc


 * 1) ! /usr/bin/perl -w
 * 2) check_rpc plugin for nagios
 * 3) usage:
 * 4)    check_rpc host service
 * 5) Check if an rpc serice is registered and running
 * 6) using rpcinfo - $proto $host $prognum 2>&1 |";
 * 7) Use these hosts.cfg entries as examples
 * 8) command[check_nfs]=/some/path/libexec/check_rpc $HOSTADDRESS$ nfs
 * 9) service[check_nfs]=NFS;24x7;3;5;5;unix-admin;60;24x7;1;1;1;;check_rpc
 * 10) initial version: 3 May 2000 by Truongchinh Nguyen and Karl DeBisschop
 * 11) Modified May 2002 Subhendu Ghosh - support for ePN and patches
 * 12) Copyright Notice: GPL
 * 1) command[check_nfs]=/some/path/libexec/check_rpc $HOSTADDRESS$ nfs
 * 2) service[check_nfs]=NFS;24x7;3;5;5;unix-admin;60;24x7;1;1;1;;check_rpc
 * 3) initial version: 3 May 2000 by Truongchinh Nguyen and Karl DeBisschop
 * 4) Modified May 2002 Subhendu Ghosh - support for ePN and patches
 * 5) Copyright Notice: GPL
 * 1) Copyright Notice: GPL
 * 1) Copyright Notice: GPL

use strict; use lib "/usr/lib/nagios/plugins"; use utils qw($TIMEOUT %ERRORS &print_revision &support); use vars qw($PROGNAME); my ($verbose,@proto,%prognum,$host,$response,$prognum,$port,$cmd,$progver,$state); my ($array_ref,$test,$element,@progkeys,$proto,$a,$b); my ($opt_V,$opt_h,$opt_C,$opt_p,$opt_H,$opt_c,$opt_u,$opt_t); my ($line, @progvers, $response2,$response3); $opt_V = $opt_h = $opt_C = $opt_p = $opt_H = $opt_u = $opt_t =''; $state = 'UNKNOWN'; $progver = $response=$response2= $response3 ='';

$PROGNAME = "check_rpc"; sub print_help ; sub print_usage ; sub in ($$);

$ENV{'BASH_ENV'}=''; $ENV{'ENV'}=''; $ENV{'PATH'}=''; $ENV{'LC_ALL'}='C';

$proto[10003]='u'; $proto[10004]='u'; $proto[10007]='u';
 * 1) Initialise protocol for each progname number
 * 2) 'u' for UDP, 't' for TCP

use Getopt::Long; Getopt::Long::Configure('bundling'); GetOptions(	"V"  => \$opt_V,   "version"    => \$opt_V,	"h"   => \$opt_h,   "help"       => \$opt_h,	"C=s" => \$opt_C,   "command=s"  => \$opt_C,	"p=i" => \$opt_p,   "port=i"     => \$opt_p, 	"H=s" => \$opt_H,   "hostname=s" => \$opt_H, 	"c=s" => \$opt_c,   "progver=s"  => \$opt_c, 	"v+"  => \$verbose, "verbose+"   => \$verbose, 	"u"   => \$opt_u,   "udp"        => \$opt_u, 	"t"   => \$opt_t,   "tcp"        => \$opt_t );

if ($opt_h) { print_help; exit $ERRORS{'OK'}; }
 * 1) -h means display verbose help screen

if ($opt_V) { print_revision($PROGNAME,'1.4.16'); exit $ERRORS{'OK'}; }
 * 1) -V means display version number


 * 1) Hash containing all RPC program names and numbers
 * 2) Add to the hash if support for new RPC program is required

%prognum = (	"portmapper"  => 100000 ,	"portmap"  => 100000 ,	"sunrpc"  => 100000 ,	"rpcbind"  => 100000 ,	"rstatd"  => 100001 ,	"rstat"  => 100001 ,	"rup"  => 100001 ,	"perfmeter"  => 100001 ,	"rstat_svc"  => 100001 ,	"rusersd"  => 100002 ,	"rusers"  => 100002 ,	"nfs"  => 100003 ,	"nfsprog"  => 100003 ,	"ypserv"  => 100004 ,	"ypprog"  => 100004 ,	"mountd"  => 100005 ,	"mount"  => 100005 ,	"showmount"  => 100005 ,	"ypbind"  => 100007 ,	"walld"  => 100008 ,	"rwall"  => 100008 ,	"shutdown"  => 100008 ,	"yppasswdd"  => 100009 ,	"yppasswd"  => 100009 ,	"etherstatd"  => 100010 ,	"etherstat"  => 100010 ,	"rquotad"  => 100011 ,	"rquotaprog"  => 100011 ,	"quota"  => 100011 ,	"rquota"  => 100011 ,	"sprayd"  => 100012 ,	"spray"  => 100012 ,	"3270_mapper"  => 100013 ,	"rje_mapper"  => 100014 ,	"selection_svc"  => 100015 ,	"selnsvc"  => 100015 ,	"database_svc"  => 100016 ,	"rexd"  => 100017 ,	"rex"  => 100017 , "alis" => 100018 , "sched" => 100019 , "llockmgr" => 100020 , "nlockmgr" => 100021 , "x25_inr" => 100022 , "statmon" => 100023 , "status" => 100024 , "bootparam" => 100026 , "ypupdated" => 100028 , "ypupdate" => 100028 , "keyserv" => 100029 , "keyserver" => 100029 , "sunlink_mapper" => 100033 , "tfsd" => 100037 , "nsed" => 100038 , "nsemntd" => 100039 , "showfhd" => 100043 , "showfh" => 100043 , "ioadmd" => 100055 , "rpc.ioadmd" => 100055 , "NETlicense" => 100062 , "sunisamd" => 100065 , "debug_svc" => 100066 , "dbsrv" => 100066 , "ypxfrd" => 100069 , "rpc.ypxfrd" => 100069 , "bugtraqd" => 100071 , "kerbd" => 100078 , "event" => 100101 , "na.event" => 100101 , "logger" => 100102 , "na.logger" => 100102 , "sync" => 100104 , "na.sync" => 100104 , "hostperf" => 100107 , "na.hostperf" => 100107 , "activity" => 100109 , "na.activity" => 100109 , "hostmem" => 100112 , "na.hostmem" => 100112 , "sample" => 100113 , "na.sample" => 100113 , "x25" => 100114 , "na.x25" => 100114 , "ping" => 100115 , "na.ping" => 100115 , "rpcnfs" => 100116 , "na.rpcnfs" => 100116 , "hostif" => 100117 , "na.hostif" => 100117 , "etherif" => 100118 , "na.etherif" => 100118 , "iproutes" => 100120 , "na.iproutes" => 100120 , "layers" => 100121 , "na.layers" => 100121 , "snmp" => 100122 , "na.snmp" => 100122 , "snmp-cmc" => 100122 , "snmp-synoptics" => 100122 , "snmp-unisys" => 100122 , "snmp-utk" => 100122 , "traffic" => 100123 , "na.traffic" => 100123 , "nfs_acl" => 100227 , "sadmind" => 100232 , "nisd" => 100300 , "rpc.nisd" => 100300 , "nispasswd" => 100303 , "rpc.nispasswdd" => 100303 , "ufsd" => 100233 , "ufsd" => 100233 , "pcnfsd" => 150001 , "pcnfs" => 150001 , "amd" => 300019 , "amq" => 300019 , "bwnfsd" => 545580417 , "fypxfrd" => 600100069 , "freebsd-ypxfrd" => 600100069 , );

if (defined $verbose && ($verbose > 1) ){ my $key; print "Supported programs:\n"; print "   name\t=>\tnumber\n"; print " ===============================\n"; foreach $key (sort keys %prognum) { print "  $key \t=>\t$prognum{$key} \n"; }	print "\n\n"; print_usage; exit $ERRORS{'OK'}; }
 * 1) -v means verbose, -v-v means verbose twice = print above hash

unless ($opt_H) { print_usage; exit $ERRORS{'UNKNOWN'}; }
 * 1) -H means host name

if (! utils::is_hostname($opt_H)){ print "$opt_H is not a valid host name\n"; print_usage; exit $ERRORS{"UNKNOWN"}; }else{ $host = $opt_H; }

if ($opt_t && $opt_u) { print "Cannot define tcp AND udp\n"; print_usage; exit $ERRORS{'UNKNOWN'}; }

$opt_C = shift unless ($opt_C); unless ($opt_C) { print_usage; exit -1; } @progkeys = keys %prognum; if ($opt_C =~ m/^([0-9]+)$/){ $prognum = $1; } elsif ( in( \@progkeys, $opt_C)) { $prognum = $prognum{$opt_C}; } else { print "Program $opt_C is not defined\n"; exit $ERRORS{'UNKNOWN'}; }
 * 1) -C means command name or number
 * 1)    $response = "RPC ok: program $opt_C (version ";
 * 1)    $response = "RPC ok: $opt_C (version ";

if($opt_p =~ /^([0-9]+)$/){ $port = "-n $1"; } else { $port = ""; }
 * 1) -p means port number

$proto = 'u'; $proto = $proto[$prognum] if ($proto[$prognum]); $proto = 't' if ($opt_t); $proto = 'u' if ($opt_u);

$SIG{'ALRM'} = sub { print ("ERROR: No response from RPC server (alarm)\n"); exit $ERRORS{"UNKNOWN"}; }; alarm($TIMEOUT);
 * 1) Just in case of problems, let's not hang Nagios

if (defined $opt_c ) { my $vers; @progvers = split(/,/ ,$opt_c ); foreach $vers (sort @progvers) { if($vers =~ /^([0-9]+)$/){ $progver = "$1"; print "Checking $opt_C version $progver proto $proto\n" if $verbose; get_rpcinfo; }else{ print "Version $vers is not an integer\n" if $verbose; }
 * 1) -c is progver  - if we need to check multiple specified versions.

} }else{ get_rpcinfo; }

if ($proto eq "u" ){ $proto = "udp"; }else{ $proto = "tcp"; }
 * 1) translate proto for output

if ($state eq 'OK') { print "$state: RPC program $opt_C".$response." $proto running\n"; }else{ if($response){ print "$state: RPC program $opt_C".$response2." $proto is not running,".$response." $proto is running\n"; }else{ print "$state: RPC program $opt_C $response2 $proto is not running\n"; } } exit $ERRORS{$state};


 * 1)  Subroutines ==========================

sub get_rpcinfo { $cmd = "$utils::PATH_TO_RPCINFO $port -". "$proto $host $prognum $progver 2>&1 |"; print "$cmd\n" if ($verbose); open CMD, $cmd or die "Can't fork for rpcinfo: $!\n" ;

while ( $line =  ) { printf "$line " if $verbose; chomp $line;

if ( $line =~ /program $prognum version ([0-9]*) ready and waiting/ ) { $response .= " version $1"; $state = 'OK' unless $state ne 'UNKNOWN'; print "1:$response \n" if $verbose; }

if ( $line =~ /program $prognum version ([0-9]*) is not available/ ) { $response2 .= " version $1"; $state = 'CRITICAL'; print "2:$response2 \n" if $verbose; }		if ( $line =~ /program $prognum is not available/ ) { $response3 = ""; $response3 = "tcp" if $opt_t; $response3 = "udp" if $opt_u; $state = 'CRITICAL'; print "3:$response3 \n" if $verbose; }	}	close CMD; }

sub print_help { print_revision($PROGNAME,'1.4.16'); print "Copyright (c) 2002 Karl DeBisschop/Truongchinh Nguyen/Subhendu Ghosh\n"; print "\n"; print "Check if a rpc service is registered and running using\n"; print "     rpcinfo -H host -C rpc_command \n"; print "\n"; print_usage; print "\n"; print "          The server providing the rpc service\n"; print "    The program name (or number).\n"; print "  The version you want to check for (one or more)\n"; print "                   Should prevent checks of unknown versions being syslogged\n"; print "                   e.g. 2,3,6 to check v2, v3, and v6\n"; print " [-u | -t]       Test UDP or TCP\n"; print " [-v]            Verbose \n"; print " [-v -v]         Verbose - will print supported programs and numbers \n"; print "\n"; support; }

sub print_usage { print "Usage: \n"; print " $PROGNAME -H host -C rpc_command [-p port] [-c program_version] [-u|-t] [-v]\n"; print " $PROGNAME [-h | --help]\n"; print " $PROGNAME [-V | --version]\n"; }

sub in ($$) { $array_ref = shift; $test = shift;

while ( $element = shift @{$array_ref} ) { if ($test eq $element) { return 1; }	}	return 0; }