From 2afd50d69a73997343d50fb37d0f7b179785fa48 Mon Sep 17 00:00:00 2001 From: Stanley Hopcroft Date: Tue, 25 Jan 2005 09:09:33 +0000 Subject: New plugin - checks that ICA master browser is what it should be (important for firewalled dialup) git-svn-id: https://nagiosplug.svn.sourceforge.net/svnroot/nagiosplug/nagiosplug/trunk@1099 f882894a-f735-0410-b71e-b25c423dba1c diff --git a/contrib/check_ica_master_browser.pl b/contrib/check_ica_master_browser.pl new file mode 100755 index 0000000..1bbab60 --- /dev/null +++ b/contrib/check_ica_master_browser.pl @@ -0,0 +1,229 @@ +#!/usr/bin/perl -w + +# $Id$ + +# $Log$ +# Revision 1.1 2005/01/25 09:09:33 stanleyhopcroft +# New plugin - checks that ICA master browser is what it should be (important for firewalled dialup) +# + +use strict ; + +use IO::Socket; +use IO::Select; +use Getopt::Long ; + +use lib qw(/usr/local/nagios/libexec) ; +use utils qw(%ERRORS &print_revision &support &usage); +use packet_utils qw(&pdump &tethereal) ; + +my $PROGNAME = 'check_ica_master_browser' ; + +# You might have to change this... + +my $PACKET_TIMEOUT = 1; + # Number of seconds to wait for further UDP packets +my $TEST_COUNT = 2; + # Number of datagrams sent without reply +my $BUFFER_SIZE = 1500; + # buffer size used for 'recv' calls. +my $ICA_PORT = 1604; + # what port ICA runs on. Unlikely to change. + +# End user config. + +my ($debug, $preferred_master, $bcast_addr, $ica_browser, $timeout) ; + +Getopt::Long::Configure('bundling', 'no_ignore_case'); +GetOptions + ("V|version" => \&version, + "h|help" => \&help, + "v|verbose" => \$debug, + "B|broadcast_addr:s" => \$bcast_addr, + "I|ica_browser:s" => \$ica_browser, + "P|preferred_master:s" => \$preferred_master, + "T|Packet_timeout:i" => \$timeout, +) ; + + +my $broadcast_addr = $1 if $bcast_addr and $bcast_addr =~ m#(\d+\.\d+\.\d+\.\d+)# ; +usage("Invalid broadcast address: $bcast_addr") + if $bcast_addr and not defined($broadcast_addr) ; + +usage("You must provide either the name of an ICA browser or the broadcast address of the subnet containing them\n") + unless ($ica_browser or $broadcast_addr) ; + +usage("You must provide the name or address of a preferred ICA master browser\n") + unless ($preferred_master) ; + +my $preferred_master_n = $preferred_master =~ m#(\d+\.\d+\.\d+\.\d+)# + ? $preferred_master + : inet_ntoa(scalar gethostbyname($preferred_master)) ; + +my $Timeout = $timeout || $PACKET_TIMEOUT ; + + # Definitions of query strings. Change at your own risk :) + # this info was gathered with tcpdump whilst trying to use an ICA client, + # so I'm not 100% sure of what each value is. + +my $bcast_helo = &tethereal(<<'End_of_Tethereal_trace', '1e') ; +0020 ff ff 04 d6 06 44 00 26 4a 76 1e 00 01 30 02 fd .....D.&Jv...0.. +0030 a8 e3 00 02 f5 95 9f f5 30 07 00 00 00 00 00 00 ........0....... +0040 00 00 00 00 00 00 01 00 ........ +End_of_Tethereal_trace + +my $direct_helo = &tethereal(<<'End_of_Tethereal_trace', '20') ; +0020 64 17 05 0f 06 44 00 28 ab b5 20 00 01 30 02 fd d....D.(.. ..0.. +0030 a8 e3 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ +0040 00 00 00 00 00 00 00 00 00 00 ........ +End_of_Tethereal_trace + +my $Udp = IO::Socket::INET->new( Proto => 'udp' ) + || die "Socket failure: $!"; + + # select is here to allow us to set timeouts on the connections. Otherwise they + # just 'stop' until a server appears. + +my $select = IO::Select->new($Udp) + || die "Select failure: $!"; + +$Udp->sockopt(SO_BROADCAST, 1 ); + +my ($remote_host, $buff, $destination, $raddr, $rport, $rhost, @remote_response); +my ($query_message, $send_addr, $this_test) ; + +$buff = ''; +$this_test = 0; + + # If there is no response to the first helo packet it will be resent + # up to $TEST_COUNT (see at the top). + +$query_message = $broadcast_addr ? $bcast_helo : $direct_helo ; +$destination = $broadcast_addr ? $broadcast_addr: $ica_browser ; +$send_addr = sockaddr_in($ICA_PORT, inet_aton($destination) ) ; + +while ( ++$this_test <= $TEST_COUNT && !$buff ) { + + print "Sending helo datagram. datagram number: ", $this_test, "\n" + if $debug ; + + print "Querying $destination for master browser\n" + if $debug ; + &pdump($query_message) + if $debug ; + $Udp->send($query_message, 0, $send_addr ); + if ( $select->can_read($Timeout) ) { + $remote_host = $Udp->recv($buff, $BUFFER_SIZE, 0 ); + } + + last + if $buff ; + sleep 1 ; + +} + + # Ok we've looped several times, looking for a response. If we don't have one + # yet, we simply mark the whole lot as being unavailable. + +unless ( $buff ) { + print "Failed. No response to helo datagram (master browser query) from $destination.\n" ; + exit $ERRORS{CRITICAL} ; +} + +($rport, $raddr) = sockaddr_in( $remote_host ); +$rhost = gethostbyaddr( $raddr, AF_INET ); +my @tmpbuf = unpack('C*', $buff ); +if ( $debug ) { + print "$rhost:$rport responded with: ",length($buff), " bytes\n"; + &pdump($buff) ; +} + + # Now we have a response, then we need to figure out the master browser, and + # query it for published applications... + +my $master_browser = join '.', @tmpbuf[32..35] ; +my ($master_browser_a) = gethostbyaddr(inet_aton($master_browser), AF_INET) =~ /^(\w+?)\./ ; + + # Ok should probably error check this, because it's remotely possible + # that a server response might be completely wrong... + +print "Master browser = $master_browser_a/$master_browser\n" + if $debug ; + +$send_addr = sockaddr_in($ICA_PORT, inet_aton($master_browser)); + +my $subject_clause = $bcast_addr ? "of the \"$destination\" subnet" : "known to ICA server \"$destination\"" ; + +if ( $master_browser eq $preferred_master_n ) { + print "Preferred master browser \"$preferred_master\" __is__ the master browser (\"$master_browser_a/$master_browser\") $subject_clause.\n" ; + exit $ERRORS{OK} ; +} else { + print "\"\u$preferred_master\" is __not__ the master browser (\"$master_browser_a/$master_browser\") $subject_clause: remote clients (dialup) may not find Published applications from Master Browser.\n" ; + exit $ERRORS{CRITICAL} ; +} + +close $Udp; + + +sub print_usage () { + print "Usage: $PROGNAME (-B | -I ) - P " ; +} + +sub print_help () { + print_revision($PROGNAME,'$Revision$ '); + print "Copyright (c) 2002 Ed Rolison/Tom De Blende/S Hopcroft + +Perl Check Citrix Master Browser plugin for Nagios. + +Returns OK if the Citrix master browser is that given by the -P option. + +The plugin works by + If the -B option is specified, sends a broadcast helo to find the address of the Citrix master browser in the specified subnet. + return critical if there is no reply; + Else if the -I option is specified + send a direct helo to the specified server until there is a response (containing the address of the Citrix master browser) + + + return Critical if the response does not contain the address of the 'preferred master browser' (-P option). + return OK + + How ICA Clients Use the Master ICA Browser. + +Citrix ICA Clients must locate the master browser to get the address of a server or published application. + +The Citrix ICA Client can locate the master browser by sending out broadcast packets, or, +if the address of a Citrix server is specified in the Citrix ICA Client or in an ICA file, +the ICA Client locates the master browser by sending directed packets to the specified address. +The ICA Client requests the address of the ICA master browser from the Citrix server. + +"; + print_usage(); + print ' +-B, --broadcast_address:STRING + The broadcast address that should contain Citrix master browser. This option takes precedence over -I. +-I, --ica_browser:STRING + Optional name or address of an ICA server that could be the master browser (used when broadcast not possible). +-P, --preferred_master:STRING + Name or address of the ICA server that _should_ be the master browser. + Required. +-T, --packet-timeout:INTEGER + Time to wait for UDP packets (default 1 sec). +-v, --verbose + Debugging output. +-h, --help + This stuff. + +'; + support(); +} + +sub version () { + print_revision($PROGNAME,'$Revision$ '); + exit $ERRORS{'OK'}; +} + +sub help () { + print_help(); + exit $ERRORS{'OK'}; +} + -- cgit v0.10-9-g596f