From d42bffffc039be319bb8c0d7d58c2ee43a03832d Mon Sep 17 00:00:00 2001 From: Stephen L Johnson Date: Thu, 17 Feb 2000 03:03:33 +0000 Subject: [PATCH] new 'page' message type and initial client autoconfigation support --- src/spong-server.pl | 197 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 187 insertions(+), 10 deletions(-) diff --git a/src/spong-server.pl b/src/spong-server.pl index 128517f..b23426a 100755 --- a/src/spong-server.pl +++ b/src/spong-server.pl @@ -24,10 +24,12 @@ use Spong::History; use Spong::Daemon; use Spong::Log; use Spong::HostGroups; +use Spong::ConfigFile; use Sys::Hostname; use File::Path; use Socket; +use IO::Socket; use Config; use Time::Local; use Getopt::Long; @@ -40,17 +42,20 @@ if (! GetOptions("debug:i" => \$debuglevel, "restart" => \$restart, exit 1; } - +Spong::Log::set_debug_context( 'debuglevel' => $debuglevel ); #if( $ARGV[0] eq "--debug" ) { $debug = 1; shift; } #if( $ARGV[0] eq "--restart" ) { $restart = 1; shift; } #if( $ARGV[0] eq "--kill" ) { $kill = 1; shift; } -$me = "@@BINDIR@@/spong-server"; -$smessage = "@@BINDIR@@/spong-message"; -$conf_file = $ARGV[0] || "@@ETCDIR@@/spong.conf"; -$hosts_file = "@@ETCDIR@@/spong.hosts"; -$groups_file = "@@ETCDIR@@/spong.groups"; +$ETCDIR = '@@ETCDIR@@'; +$BINDIR = '@@BINDIR@@'; + +$me = "$BINDIR/spong-server"; +$smessage = "$BINDIR/spong-message"; +$conf_file = $ARGV[0] || "$ETCDIR/spong.conf"; +$hosts_file = "$ETCDIR/spong.hosts"; +$groups_file = "$ETCDIR/spong.groups"; $datafunc_path = "@@LIBDIR@@/Spong/plugins"; ($HOST) = gethostbyname(&Sys::Hostname::hostname()); $HOST =~ tr/A-Z/a-z/; @@ -79,6 +84,10 @@ if (defined $SPONG_UPDATE_PORT ) { $PROCS{'spong-update'} = { func => \&listen_for_updates, pid => undef }; } +if (defined $SPONG_CLIENT_PORT ) { + $PROCS{'client'} = { func => \&listen_for_clients, pid => undef }; +} + # Establish a list of all the services that we monitor so that we can be # consistant in the output that we display regardless of the group that we @@ -141,6 +150,54 @@ sub usage { } +# This procedure listens for client connections connections (the client port), +# and reponse to queries or request for configuration files. + +sub listen_for_clients { + my ( $sock, $client ); + + # Set up the socket to listen to + $SIG{'PIPE'} = 'IGNORE'; + $SIG{'TERM'} = $SIG{'HUP'} = $SIG{'QUIT'} = sub { + &debug('spong client caught QUIT signal, exiting',3); + undef $sock; exit; + }; + + $sock = IO::Socket::INET->new( Listen => SOMAXCONN, +# LocalHost => INADDR_ANY, + LocalPort => $main::SPONG_CLIENT_PORT, + Proto => 'tcp', + Timeout => 30, + Reuse => 1, + ); + if (! defined $sock ) { die "socket: $!"; } + + &debug( "client socket setup, listening for connections" ); + + while( 1 ) { + next unless ( $client = $sock->accept() ); + + $paddr = $client->peerhost(); + +&debug("[$$] Connection from $paddr"); + + # &validate_connection( $paddr ); - need to do something here... + + # Read all from the client, and disconnect, we process the message next. + + my $header = <$client>; chomp $header; +&debug("[$$] header = $header"); + + # Now depending on what kind of message it is, pass it off to a routine + # that can process the message. + + if( $header =~ /^status\b/ ) { &client_status( $client, $header ); } + if( $header =~ /^get\b/ ) { &client_get( $client, $header ); } + + undef $client; + + } +} # This procedure listens for connections at port 1970 (the update port), and # each time a connection is made, it grabs the info that is being sent to us, @@ -190,6 +247,7 @@ sub listen_for_updates { if( $header =~ /^status\b/ ) { &save_status( $header, $message ); next; } if( $header =~ /^event\b/ ) { &save_event( $header, $message ); next; } + if( $header =~ /^page\b/ ) { &save_page( $header, $message ); next; } if( $header =~ /^ack-del\b/ ) { &del_ack( $header, $message ); next; } if( $header =~ /^ack\b/ ) { &save_ack( $header, $message ); next; } # if( $header =~ /^config\b/ ) { &save_config( $header, $message ); } @@ -321,6 +379,64 @@ sub listen_for_queries { } } +# =========================================================================== +# Client configuare methods. These all take messages from clients and sends +# configuration file or info about configuration file back +# =========================================================================== + +# Return status information about configuration files for a host + +sub client_status { + my( $client, $header ) = @_; + + my( $host, $file ) = ( "", "" ); + if ( $header =~ /\S+ (\S+) (\S+)/ ) { $host = $1; $file = $2; } + + if ( ! $main::HOSTS{$host} && $host ne 'DEFAULT') { + $client->print("ERROR Host $host is not defined"); + return; + } + + # Get a Configuration file object for the host + my $cf = new Spong::ConfigFile( $host, $file ); + if ( ! $cf ) { + $client->print("ERROR Configuration file $file not found"); + return; + } + + # Build the status line and return it to the client + $sts = "OK " . $cf->host() . " " . $cf->name() . " " . $cf->timestamp() . + " " . $cf->size() . " " . $cf->lines(); + $client->print("$sts\n"); + +} + +sub client_get { + my( $client, $header ) = @_; + + my( $host, $file ) = ( "", "" ); + if ( $header =~ /\S+ (\S+) (\S+)/ ) { $host = $1; $file = $2; } + + if ( ! $main::HOSTS{$host} && $host ne 'DEFAULT') { + $client->print("ERROR Host $host is not defined"); + return; + } + + # Get a Configuration file object for the host + my $cf = new Spong::ConfigFile( $host, $file ); + if ( ! $cf ) { + $client->print("ERROR Configuration file $file not found"); + return; + } + + my $contents = $cf->contents(); + + foreach ( @$contents ) { $client->print($_); } + +} + + + # =========================================================================== # Database update methods. These all take messages from clients and update # specific parts of the database. @@ -466,6 +582,65 @@ sub save_event { } + +# Take the incoming page message, run it through some error checking, +# and send the information off to spong-message and let it decide if it +# should page/email someone... + +sub save_page { + my( $header, $message ) = @_; + my( $cmd, $host, $service, $color, $time, $sum, $path, $start, $duration ); + my( $ttl ) = 0; + + # Do some checking on the message. If it appears bogus, then just + # log a message, and close the connection. + + if( $header =~ /^(\w+) (\S+) (\w+) (\w+) (\d+) (.*)$/ ) { + ($cmd, $host, $service, $color, $time, $sum) = ($1, $2, $3, $4, $5, $6); + + if( $host !~ m/^[a-z0-9_\-\.]+$/ ) { + &error( "save_status: invalid host [$host]" ); return; } + if( $service !~ m/^[a-z0-9_\-\.]+$/ ) { + &error( "save_status: invalid service [$service]" ); return; } + if( $color ne "red" && $color ne "yellow" && $color ne "green" ) { + &error( "save_status: invalid color [$color]" ); return;} + if( $time !~ m/^\d+$/ ) { + &error( "save_status: invalid time [$time]" ); return; } + } else { + &error( "save_status: invalid header [$header]" ); return; + } + + if ($main::HOSTS{$host} eq "") { + &error("save_status: undefined host [$host]"); + return; + } + + # Call message_user()... + +# $duration = $time - $start; + &message_user( "page", $host, $service, $color, $time, $sum ); + + # Save the status information to the history table and state file as well. + + # Update the history file + if (0) { + $data = "page $time $service $color $sum\n"; + &save_data( ">>", "$SPONGDB/$host/history/current", $data); + + # If status history is enabled, save status message for history event + if ( $STATUS_HISTORY ) { + # Save the status update information + $data = "timestamp $start $time\ncolor $color\n$time $sum\n$message\n"; + &save_data( ">>", "$SPONGDB/$host/history/status/$time-$service", + $data); + } + } + +} + + + + # Take a BigBrother status message and convert it to a Spong status # message and send it to save_status for processing @@ -763,7 +938,7 @@ sub init_logging { $debug = ($debuglevel == 0) ? 1 : $debuglevel } - Spong::Log::set_debug_context( "debuglevel" => $debug ); + Spong::Log::set_debug_context( 'debuglevel' => $debug ); my $filename = ($SPONG_LOG_FILE) ? "$SPONGTMP/spong-server.log" : ""; my $syslog = ($SPONG_LOG_SYSLOG) ? 1 : 0; @@ -786,13 +961,12 @@ sub init_logging { sub message_user { my ( $cmd, $host, $service, $color, $time, $sum, $duration ) = @_; - if ($SEND_MESSAGE eq 'NONE') { return; } - if (! defined $duration || $duration eq "") { $duration = 0; } $SIG{'CHLD'} = 'IGNORE'; - if ( $cmd eq "status" ) { + # if message type was 'status' and messaging is allowed + if ( $cmd eq "status" && $SEND_MESSAGE ne 'NONE' ) { # If the color is 'red' and duration is non-zero, call spong-message for # escalation notifications @@ -831,6 +1005,9 @@ sub message_user { &send_message( $host, $service, $color, $time, $sum, $duration ); } } + } elsif ( $cmd eq "page" && $PAGE_MESSAGE eq 'PAGE' ) { + &debug("sending a page message notification",2); + &send_message( $host, $service, $color, $time, $sum, $duration ); } $SIG{'CHLD'} = \&chld_handler; -- 2.30.2