#!/usr/bin/perl -w

# WARNING WARNING WARNING WARNING WARNING WARNING WARNING
# This is a hack.  Not an acceptable long-term solution.
# The only guarantee that comes with this script is that
# it is definitely insecure.
# WARNING WARNING WARNING WARNING WARNING WARNING WARNING

#additional header for sockets handling
use IO::Socket;
#used for the function gethostbyaddr
use Net::hostent;

#you have to specify the port number after the perl command
my $port=shift || die "Usage server.pl <port>\n";

my %CMD_CODES = ( 
  'SCHEDULE_SVC_CHECK' => 7,
  'SCHEDULE_HOST_SVC_CHECKS' => 17,
  'SCHEDULE_FORCED_HOST_SVC_CHECKS' => 53,
  'SCHEDULE_FORCED_SVC_CHECK' => 54,
  'SCHEDULE_HOST_DOWNTIME' => 55,
  'SCHEDULE_SVC_DOWNTIME' => 56,
  'SCHEDULE_HOSTGROUP_HOST_DOWNTIME' => 84,
  'SCHEDULE_HOSTGROUP_SVC_DOWNTIME' => 85,
  'SCHEDULE_HOST_SVC_DOWNTIME' => 86,
  'SCHEDULE_HOST_CHECK' => 96,
  'SCHEDULE_FORCED_HOST_CHECK' => 98,
  'SCHEDULE_SERVICEGROUP_HOST_DOWNTIME' => 121,
  'SCHEDULE_SERVICEGROUP_SVC_DOWNTIME' => 122,
  'SCHEDULE_AND_PROPAGATE_TRIGGERED_HOST_DOWNTIME' => 134,
  'SCHEDULE_AND_PROPAGATE_HOST_DOWNTIME' => 137,
);


####
#creation of the socket called $server:
#Proto= protocol to use
#LocalPort = service name or port number to be the server
#ports < 1024 under linux are restricted to the superuser
#Listen = number of pending connections, SOMAXCON is
#a special symbol for the system maximum
#Reuse = restart the server manually
####

my $server = IO::Socket::INET->new( Proto => 'tcp',
                                    LocalPort => $port,
                                    Listen => SOMAXCONN,
                                    Reuse => 1);

die "can't setup server" unless $server;
print "[Server $0 is running]\n";

####
#the server waits for a client to connect
#and accept it with $server->accept
#you can telnet to the port you want to test it
####
while ($client = $server->accept()) {
  $client->autoflush(1);

  # Only talk to 10.2.3.4
  if ($client->peerhost ne '10.2.3.4') {
    print $client "Sorry.  I'm not supposed to talk to strangers.\n";
    printf "[Reject connect from %s]\n", $client->peerhost;
    close($client);
    next;
  }
  #welcome
  print $client "Welcome to $0\n";

  ####
  #get informations on the client
  #peeraddr = client name or IP
  ####
  $hostinfo = gethostbyaddr($client->peeraddr);

  #print this informations on the server side
  printf "[Connect from %s]\n", $hostinfo->name || $client->peerhost;

  #ask the client for a command
  print $client "[server]\$";
  while (my $request = <$client>) {
    next unless $request =~ /\S/; # blank line
    #quit/exit
    if ($request =~ /^quit/i) { 
      last;
    } elsif ($request =~ /^date/i) { 
      printf $client "%s\n", scalar localtime;
    } else {
	if (handleRequest($request)) {
	  print $client "Done.\n";
	} else {
	  print $client "There was a problem.\n";
	}
    }
  } continue {
    print $client "[server]\$ ";
  }
  close $client;
}
#the socket $client is closed
#to close the socket $server: ctrl+c 

sub handleRequest {
  my ($request) = @_;
  chomp($request);
  my @request = split(';', $request);
  my $TYPE = $CMD_CODES{ $request[0] };
  my $HOST = $request[1];
  my $SERVICE = "";
  if ($request[0] eq 'SCHEDULE_SVC_DOWNTIME') {
    $SERVICE = "&service=$request[2]";
    shift(@request);
  }
  chomp(my $START=`/bin/date -d \@$request[2] '+%m-%d-%Y %H:%M:%S'`);
  chomp(my $END=`/bin/date -d \@$request[3] '+%m-%d-%Y %H:%M:%S'`);  
  my $COMMENT=$request[8];
  $ENV{QUERY_STRING}="cmd_typ=${TYPE}&cmd_mod=2&host=${HOST}${SERVICE}&com_author=foo&com_data=${COMMENT}&trigger=0&start_time=${START}&end_time=${END}&fixed=1";
  $ENV{REMOTE_USER}="some_nagios_user";
  $ENV{REQUEST_METHOD}="GET";
#  print "$ENV{QUERY_STRING}\n";
  open(FH, "/apps/nagios/sbin/cmd.cgi|");
  my $result = join("", <FH>);
  close(FH);
  unless ($result =~ /successfully submitted/) {
    open(MAIL, "|/usr/bin/mailx -s 'failed to schedule downtime' admin\@someplace.com");
    print MAIL "
HOST: $HOST
SERVICE: $SERVICE
START: $START
END: $END
COMMENT: $COMMENT

-----------------------------------------------------
$result
";
    close(MAIL);
  }
  return 1;
}
