--- projects/cms/source/host/ihost-perl/ihost.pl 2001/11/20 12:47:03 1.41 +++ projects/cms/source/host/ihost-perl/ihost.pl 2002/05/18 18:15:56 1.49 @@ -1,5 +1,24 @@ #!/usr/bin/perl -w +# +# i-scream central monitoring system +# Copyright (C) 2000-2002 i-scream +# +# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# + # ----------------------------------------------------------- # Perl i-scream Host. # http://www.i-scream.org.uk @@ -8,7 +27,7 @@ # a typical Unix/Linux box. # # $Author: tdb $ -# $Id: ihost.pl,v 1.41 2001/11/20 12:47:03 tdb Exp $ +# $Id: ihost.pl,v 1.49 2002/05/18 18:15:56 tdb Exp $ #------------------------------------------------------------ $| = 1; @@ -33,6 +52,8 @@ use vars qw ( $fqdn $pidfile $retry_wait + $ostype + $key @data ); @@ -46,15 +67,21 @@ $filter_manager_port = $ARGV[1]; $seq_no = 1; $retry_wait = 60; +# work out our platform, if we can. +$ostype = `uname -s`; +chomp $ostype; +$ostype = "unknown" if not defined $ostype; + # write our PID to a file # use home dir by default -$pidfile = $ENV{"HOME"}; +#$pidfile = $ENV{"HOME"}; # or drop it in /var/tmp if we can't find HOME $pidfile = "/var/tmp" if not defined $pidfile; $pidfile .= "/.ihost.pid"; &write_pid(); &tcp_configure(); +&send_tcp_heartbeat(); &send_udp_packet(); $last_udp_time = time; @@ -134,63 +161,63 @@ sub tcp_configure() { print $sock "LASTMODIFIED\n"; $response = <$sock>; - if (!$response) { - print "The i-scream server did not return anything for the LASTMODIFIED command.\n"; + if (!$response || $response eq "ERROR\n") { + print "The i-scream server did not provide the LASTMODIFIED value.\n"; close($sock); wait_then_retry(); next; } - chop $response; + chomp $response; $last_modified = $response; print "Config last modified: ". (scalar localtime $last_modified/1000) . "\n"; print $sock "FILELIST\n"; $response = <$sock>; - if (!$response) { + if (!$response || $response eq "ERROR\n") { print "The i-scream server did not provide a configuration file list.\n"; close($sock); wait_then_retry(); next; } - chop $response; + chomp $response; $file_list = $response; print "File list obtained: $file_list\n"; print $sock "FQDN\n"; $response = <$sock>; - if (!$response) { + if (!$response || $response eq "ERROR\n") { print "The i-scream server did not tell us our FQDN.\n"; close($sock); wait_then_retry(); next; } - chop $response; + chomp $response; $fqdn = $response; print "FQDN returned: $fqdn\n"; print $sock "UDPUpdateTime\n"; $response = <$sock>; - if (!$response) { + if (!$response || $response eq "ERROR\n") { print "The i-scream server did not give us a UDPUpdateTime.\n"; close($sock); wait_then_retry(); next; } - chop $response; + chomp $response; $udp_update_time = $response; print $sock "TCPUpdateTime\n"; $response = <$sock>; - if (!$response) { + if (!$response || $response eq "ERROR\n") { print "The i-scream server did not give us a TCPUpdateTime.\n"; close($sock); wait_then_retry(); next; } - chop $response; + chomp $response; $tcp_update_time = $response; print "UDP packet period: $udp_update_time seconds.\nTCP heartbeat period: $tcp_update_time seconds.\n"; @@ -214,14 +241,14 @@ sub tcp_configure() { wait_then_retry(); next; } - chop $response; - $response =~ /^(.*);(.*);(.*)/; + chomp $response; if ($response eq "ERROR") { print "There are no active configured filters for your host.\n"; close($sock); wait_then_retry(); next; } + $response =~ /^(.*);(.*);(.*)/; ($filter_addr, $udp_port, $tcp_port) = ($1, $2, $3); unless (defined($filter_addr) && defined($udp_port) && defined($tcp_port)) { print "Failed: Filter address response from server did not make sense: $response\n"; @@ -266,7 +293,7 @@ sub send_udp_packet() { opendir PLUGINS, $plugins_dir; my(@plugins) = readdir PLUGINS; foreach my $plugin (@plugins) { - push @data, `$plugins_dir/$plugin` if -x "$plugins_dir/$plugin" && -f "$plugins_dir/$plugin"; + push @data, `$plugins_dir/$plugin $ostype` if -x "$plugins_dir/$plugin" && -f "$plugins_dir/$plugin"; } # get some extra data @@ -275,18 +302,19 @@ sub send_udp_packet() { $ip = inet_ntoa(scalar(gethostbyname(hostname())) || 'localhost') or $ip = 'localhost'; # add some extra data to the array - push(@data, "packet.attributes.seq_no=$seq_no"); - push(@data, "packet.attributes.machine_name=$fqdn"); - push(@data, "packet.attributes.date=$date"); - push(@data, "packet.attributes.type=data"); - push(@data, "packet.attributes.ip=$ip"); + push(@data, "packet.attributes.seq_no $seq_no"); + push(@data, "packet.attributes.machine_name $fqdn"); + push(@data, "packet.attributes.date $date"); + push(@data, "packet.attributes.type data"); + push(@data, "packet.attributes.ip $ip"); + push(@data, "packet.attributes.key $key"); # sort the data - @data = sort(@data); - + @data = sort(grep(!/^$/, grep(/^packet\./, @data))); + # turn the array into some nice XML my($xml) = &make_xml("", ""); - + my($sock) = new IO::Socket::INET ( PeerPort => $udp_port, PeerAddr => $filter_addr, @@ -368,6 +396,9 @@ sub send_tcp_heartbeat() { return; } + print $sock "KEY\n"; + $key = <$sock>; + print $sock "ENDHEARTBEAT\n"; $response = <$sock>; if (!$response eq "OK\n") { @@ -407,27 +438,53 @@ sub make_xml() { my($curlevel, $curline) = @_; my($xmltemp) = ""; my($curtag) = ""; my($attributes) = ""; while(1) { - $curline = shift(@data) if $curline eq ""; chomp $curline; + $curline = shift(@data) if $curline eq ""; + return $xmltemp if not defined $curline; + chomp $curline; + # dealing with nest (or attributes) if($curline =~ /^$curlevel([^\.\s]+\.)/) { $curtag=$1; + if($curline =~ /^$curlevel$curtag([^\.\s]+)\s+(.*)$/) { + $xmltemp .= &make_xml("$curlevel$curtag", $curline); + } + elsif($curline =~ /^$curlevel$curtag(attributes)\.([^\.\s]+)\s+(.*)$/) { + $attributes .= " $2=\"$3\""; + } + else { + $xmltemp .= &make_xml("$curlevel$curtag", $curline); + } + my($nextline) = $data[0]; chomp $nextline if defined $nextline; + $curtag =~ s/(.*)\./$1/; + if((defined $nextline) && ($nextline =~ /^$curlevel$curtag\./)) { + $curline = ""; + } + else { + $xmltemp = "<$curtag$attributes>$xmltemp" unless $curtag eq ""; + return $xmltemp; + } } - if($curline =~ /^$curlevel$curtag([^\.\s]+)\s+(.*)$/) { - $xmltemp .= "<$1$attributes>$2"; + # dealing with value + elsif($curline =~ /^$curlevel([^\.\s]+)\s+(.*)$/) { + $curtag=$1; + $xmltemp=$2; + my($nextline) = $data[0]; chomp $nextline if defined $nextline; + if(defined $nextline && ($nextline =~ /^$curlevel$curtag\./ || $nextline =~ /^$curlevel$curtag\s+/)) { + $curline = ""; + } + else { + $xmltemp = "<$curtag$attributes>$xmltemp" unless $curtag eq ""; + return $xmltemp; + } } - elsif($curline =~ /^$curlevel$curtag(attributes)\.([^\.=]+)=(.*)$/) { - $attributes .= " $2=\"$3\""; - } - else { - $xmltemp .= &make_xml("$curlevel$curtag", $curline); - } - my($nextline) = $data[0]; chomp $nextline if defined $nextline; - $curtag =~ s/(.*)\./$1/; - if((defined $nextline) && ($nextline =~ /^$curlevel$curtag\./)) { - $curline = ""; - } - else { - $xmltemp = "<$curtag$attributes>$xmltemp" unless $curtag eq ""; - return $xmltemp; - } + # dealing with a null value + elsif($curline =~ /^$curlevel([^\.\s]+)$/) { + # simply adding a space makes the above elsif deal with it :) + # just level with an empty tag in the XML + $curline .= " "; + } + # failing all that, skip the line + else { + $curline = ""; + } } }