Code

Fix for regex input of '|', being output causing problems with Nagios' parsing of
[nagiosplug.git] / contrib / check_lotus.pl
1 #!/usr/bin/perl -w
3 # $Id: check_lotus.pl 1096 2005-01-25 09:04:26Z stanleyhopcroft $
5 # Revision 1.1  2005/01/25 09:04:26  stanleyhopcroft
6 # New plugin to check responsiveness of Louts Notes (v5 at least) servers
7 #
8 # Revision 1.10  2005-01-25 15:44:07+11  anwsmh
9 # 1 use packet_utils instead of hard coding subroutines (pdump and tethereal)
10 # 2 redo indentation using tabs (set at 4 spaces)
11 #
13 use strict ;
15 use IO::Socket;
16 use Getopt::Long ;
18 my ($timeout, $debug, $lotus_host, $server, $indiv_dn, $packet_debug) ;
20 use lib qw(/usr/local/nagios/libexec) ;
21 use utils qw($TIMEOUT %ERRORS &print_revision &support &usage) ;
22 use packet_utils qw(pdump &tethereal) ;
24 my $PROGNAME = 'check_lotus_notes' ;
26 sub print_help ();
27 sub print_usage ();
28 sub help ();
29 sub version ();
31 my $TEST_COUNT          = 2 ;
32                                                                                 # Number of Lotus client hellos sent without reply 
33 my $BUFFER_SIZE         = 1500 ;
34                                                                                 # buffer size used for 'recv' calls.
35 my $LOTUS_PORT          = 1352 ;
37 Getopt::Long::Configure('no_ignore_case');
38 GetOptions
39         ("V|version"     => \&version,
40          "h|help"        => \&help,
41          "v|debug"       => \$debug,
42          "vv|i_packet_debug"       => \$packet_debug,
43          "H|lotus_host=s"=> \$lotus_host,
44          # "I|indivual_dn:s" => \$indiv_dn,
45          "S|server:s"    => \$server,
46          "T|t_timeout:i" => \$timeout,
47 ) ;
49 usage("You must provide the DNS name or IP (v4) address of the Lotus server to be checked.\n")
50         unless $lotus_host and (
51              $lotus_host =~ m#^\d+\.\d+\.\d+\.\d+$# or
52              $lotus_host =~ m#^[\w\._-]+$#
53         ) ;
55 $server  ||= $lotus_host
56         if $lotus_host =~ m#^[\w-]+$# ;
58 usage("You must provide a server option unless the lotus_host option looks like an unqualified host name.\n")
59         unless $server ;
61 $timeout                ||= $TIMEOUT ;
62 $debug                  = 1 
63         if $packet_debug ;
65 my $server_dn   = "CN=\U$server" . '(?:/\w+=[\w -]+)*' ;
67                                                                                 # Definitions of query strings. Change at your own risk :)
68                                                                                 # This info was gathered with tcpdump while using a Lotus Notes 5 client,
69                                                                                 # so I'm not sure of what each value is.
71 my $lotus_client_hello = &tethereal(<<'End_of_Tethereal_trace', '82') ;
72 0030  ff ff dc c5 00 00 82 00 00 00 77 00 00 00 02 00   ..........w.....
73 0040  00 40 02 0f 00 07 00 39 05 9e 45 54 ad ad 03 00   .@.....9..ET....
74 0050  00 00 00 02 00 2f 00 00 00 00 00 00 00 00 00 40   ...../.........@
75 0060  1f a0 af 19 d8 92 da 37 78 c9 ce 60 5e 35 b8 f7   .......7x..`^5..
76 0070  4e 05 00 10 00 0d 00 00 00 00 00 00 00 00 00 00   N...............
77 0080  00 00 00 00 00 02 00 08 00 9c dc 22 00 7c 6f 25   ...........".|o%
78 0090  4a 08 00 10 00 00 00 00 00 00 00 00 00 00 00 00   J...............
79 00a0  00 00 00 00 00 04 00 10 00 ba ac 8c 49 67 ee a1   ............Ig..
80 00b0  22 6f 63 bb 04 b4 75 0b 8f 00                     "oc...u...
81 End_of_Tethereal_trace
83                                                                                 # XXXX
84                                                                                 # Notes 5 accepts this
85                                                                                 # _wrongly_ encoded DN
86                                                                                 # but in general the 
87                                                                                 # server will reset
88                                                                                 # the connection if
89                                                                                 # it receives malformed
90                                                                                 # packets.
92 my $lotus_client_m1 = &tethereal(<<'End_of_Tethereal_trace', 'de') ;
93 0000  de 00 00 00 d4 00 00 00 13 00 00 40 01 00 9e 45  ...........@...E
94 0010  54 ad ad 03 00 00 00 00 02 00 29 13 23 00 b9 68  T.........).#..h
95 0020  25 00 9f 87 27 00 8f f4 25 00 00 00 88 00 24 00  %...'...%.....$.
96 0030  28 00 00 00 42 56 04 00 31 2e 30 00 42 43 01 00  (...BV..1.0.BC..
97 0040  03 42 41 01 00 30 42 4c 02 00 76 02 4e 4e 50 00  .BA..0BL..v.NNP.
98 0050  cf ee 9d 19 99 ca e0 bf 97 d3 59 a1 c5 78 16 82  ..........Y..x..
99 0060  76 09 8c 2c 96 ae 5a c1 15 bd 4e e9 b7 0f a9 d4  v..,..Z...N.....
100 0070  5a 03 d9 0d bc e4 7d 4f e0 f2 79 89 cf cd 23 19  Z.....}O..y...#.
101 0080  40 55 98 81 98 be d9 17 8d 69 8e 09 de c8 e8 92  @U.......i......
102 0090  24 86 6f 5a 09 81 1f 71 be 29 b7 47 78 8c 2e 00  $.oZ...q.).Gx...
103 00a0  45 4e 04 00 95 63 00 00 4d 41 08 00 64 a1 b4 b3  EN...c..MA..d...
104 00b0  a1 01 45 c2 80 00 50 55 52 53 41 46 22 00 43 4e  ..E...PURSAF".CN
105 00c0  3d 4d 72 20 46 6f 6f 2f 4f 55 3d 42 61 72 20 68  =Mr Foo/OU=Bar h
106 00d0  6f 74 65 6c 2f 4f 3d 42 61 7a 20 4a 75 6e 63 74  otel/O=Baz Junct
107 00e0  69 6f 6e                                         ion
108 End_of_Tethereal_trace
110 my $buff = '';
112 my $valid_resp_cr = sub {
113         my ($resp, $dn, $err_ind_sr) = @_ ;
114         if ( $resp =~ /($dn)/ ) {
115                 return $1 
116         } else {
117         ($$err_ind_sr) = $resp =~ m#(CN=[\w -]+(?:/\w+=[\w -]+)*)# ;
118         return 0 ;
119         }
120 } ;
122 my @send = (
123         { Msg => 'Helo',        Send => $lotus_client_hello,    Ok => $valid_resp_cr },
124         { Msg => 'm1',          Send => $lotus_client_m1,               Ok => $valid_resp_cr },
125 ) ;
127 my $tcp ;
129 eval {
131         $tcp = IO::Socket::INET->new(Proto => 'tcp', PeerAddr => $lotus_host, PeerPort => $LOTUS_PORT, Timeout => $timeout)
132                                                                                 # Some versions (eg 1.1603) croak on a connect failure ..
133 } ;
135 &outahere("Connect to $lotus_host:$LOTUS_PORT failed:", $@)
136   if $@ || ! defined($tcp) ;
138 my $found = '' ;
140 foreach (@send) {
142         print STDERR "Sending Lotus client $_->{Msg} to $lotus_host.\n"
143                 if $debug ;
145         &pdump($_->{Send})
146                 if $packet_debug ;
148         eval {
150                 local $SIG{"ALRM"} = sub { die 'Alarm clock restart' } ;
152                 alarm($timeout) ;
154                 $tcp->send($_->{Send}, 0) ||
155                         &outahere("Send to $lotus_host failed: $!") ;
157                 defined( $tcp->recv($buff, $BUFFER_SIZE, 0 ) )  ||
158                         &outahere("Recv from $lotus_host failed: $!")
160         } ;
162         alarm(0) ;
164         &outahere('Unexpected exception raised by eval:', $@)
165                 if $@ and $@ !~ /Alarm clock restart/ ;
167         &outahere("Timeout after $timeout secs - no response from $lotus_host")
168                 if  $@ and $@ =~ /Alarm clock restart/ ;
170         &outahere("Lotus server $lotus_host reset connection - client protocol (malformed packet sent) error", $@)
171                 if  $@ and $@ =~ /reset/ ;
173         &outahere("Empty recv buff after sending client $_->{Msg} and waiting $timeout secs. NB _no_ timeout exception.")
174                 unless $buff ;
176         &pdump($buff)
177                 if $packet_debug ;
179         my $err = '' ;
181         &outahere(qq(Response from $lotus_host failed to match CN=$server/.. got "$err") ) 
182                 unless $found = $_->{Ok}->($buff, $server_dn, \$err) ;
184         print STDERR "Received Ok reply from $lotus_host - found DN $found in response.\n"
185                 if $debug ;
189 close $tcp;
191 print "Ok. Lotus server $lotus_host responded with $found after ", scalar @send, " packet dialogue.\n" ;
192 exit $ERRORS{OK} ;
194 =begin comment
196 Normal response from Lotus Notes 5 server 
198 0000  74 00 00 00 69 00 00 00 03 00 00 40 02 0f 00 05  t...i......@....
199 0010  00 3d 05 60 f0 3a 38 03 03 00 00 00 00 02 00 2f  .=.`.:8......../
200 0020  00 26 00 00 00 00 00 00 00 40 1f 3d 73 76 0e 57  .&.......@.=sv.W
201 0030  e0 d7 67 cd a3 50 10 e0 99 24 b4 43 4e 3d 43 42  ..g..P...$.CN=CB
202 0040  52 4e 4f 54 45 53 30 31 2f 4f 55 3d 53 45 52 56  RNOTES01/OU=SERV
203 0050  45 52 53 2f 4f 3d 49 50 41 75 73 74 72 61 6c 69  ERS/O=IPAustrali
204 0060  61 05 00 10 00 09 00 00 00 00 00 00 00 00 00 00  a...............
205 0070  00 00 00 00 00 00   
207 =end comment
209 =cut
211 sub outahere {
212         print "Failed. @_.\n" ;
213         exit $ERRORS{CRITICAL} ;
216 sub print_usage () {
217         print "Usage: $PROGNAME -H <lotus_host (name _or_ address)>..) [-S <lotus_server name> -T <timeout> -v ]\n";
220 sub print_help () {
221         print_revision($PROGNAME,'$Revision: 1096 $ ');
222         print "Copyright (c) 2004 Ed Rolison/S Hopcroft
224 Perl Check Lotus Notes plugin for Nagios.
226 Returns OK if the named server responds with its name.
228 ";
229         print_usage();
230         print '
231 -H, --lotus_host:STRING
232     Name or IP Address of Lotus server to be checked.
233 -I, --individual_dn:NOT IMPLEMENTED
234     String of form CN=\w+(?:/OU=\w+)?/O=\w+ 
235 -S, --server:STRING
236     Alpha numeric string specifying the Lotus server name (the CN by which the server is known by
237     in the Domino directory). Defaults to host name if the host name does not look like an IP address.
238 -T, --packet-timeout:INTEGER
239    Time to wait for TCP dialogue to complete = send + rcv times (default Nagios timeout [$TIMEOUT sec]).
240 -v, --debug
241    Debugging output.
242 -vv, --packet_debug
243    Packet dump. Please post to Nag users in the event of trouble with this plugin.
244 -h, --help
245    This stuff.
247 ';
248         support();
251 sub version () {
252         print_revision($PROGNAME,'$Revision: 1096 $ ');
253         exit $ERRORS{'OK'};
256 sub help () {
257         print_help();
258         exit $ERRORS{'OK'};