#! /usr/bin/perl -w # # check_rpc plugin for nagios # # usage: # check_rpc host service # # Check if an rpc serice is registered and running # using rpcinfo - $proto $host $prognum 2>&1 |"; # # Use these hosts.cfg entries as examples # # command[check_nfs]=/some/path/libexec/check_rpc $HOSTADDRESS$ nfs # service[check_nfs]=NFS;24x7;3;5;5;unix-admin;60;24x7;1;1;1;;check_rpc # # initial version: 3 May 2000 by Truongchinh Nguyen and Karl DeBisschop # Modified May 2002 Subhendu Ghosh - support for ePN and patches # current status: $Revision: 1.8 $ # # Copyright Notice: GPL # $Id: check_rpc.pl,v 1.8 2003/08/10 12:11:49 kdebisschop Exp $ # 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'; #Initialise protocol for each progname number # 'u' for UDP, 't' for TCP $proto[10003]='u'; $proto[10004]='u'; $proto[10007]='u'; 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 ); # -h means display verbose help screen if ($opt_h) { print_help(); exit $ERRORS{'OK'}; } # -V means display version number if ($opt_V) { print_revision($PROGNAME,'$Revision: 1.8 $ '); exit $ERRORS{'OK'}; } # Hash containing all RPC program names and numbers # 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 , ); # -v means verbose, -v-v means verbose twice = print above hash 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'}; } # -H means host name unless ($opt_H) { print_usage(); exit $ERRORS{'UNKNOWN'}; } 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'}; } # -C means command name or number $opt_C = shift unless ($opt_C); unless ($opt_C) { print_usage(); exit -1; } @progkeys = keys %prognum; if ($opt_C =~ m/^([0-9]+)$/){ # $response = "RPC ok: program $opt_C (version "; $prognum = $1; } elsif ( in( \@progkeys, $opt_C)) { # $response = "RPC ok: $opt_C (version "; $prognum = $prognum{$opt_C}; } else { print "Program $opt_C is not defined\n"; exit $ERRORS{'UNKNOWN'}; } # -p means port number if($opt_p =~ /^([0-9]+)$/){ $port = "-n $1"; } else { $port = ""; } $proto = 'u'; $proto = $proto[$prognum] if ($proto[$prognum]); $proto = 't' if ($opt_t); $proto = 'u' if ($opt_u); # Just in case of problems, let's not hang Nagios $SIG{'ALRM'} = sub { print ("ERROR: No response from RPC server (alarm)\n"); exit $ERRORS{"UNKNOWN"}; }; alarm($TIMEOUT); # -c is progver - if we need to check multiple specified versions. 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; } } }else{ get_rpcinfo(); } ## translate proto for output if ($proto eq "u" ){ $proto = "udp"; }else{ $proto = "tcp"; } 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}; ######## 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,'$Revision: 1.8 $ '); 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; }