#!/usr/bin/perl
###############################################################################
#                                                                             #
# IPFire.org - A linux based firewall                                         #
# Copyright (C) 2015-2016  IPFire Development Team                            #
#                                                                             #
# 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 3 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, see <http://www.gnu.org/licenses/>.       #
#                                                                             #
###############################################################################

use strict;
use Switch;

require Guardian::Base;
require Guardian::Daemon;
require Guardian::Socket;

use warnings;

# Define version.
my $version ="2.0.2";

# Assign given command line arguments some pretty variable names.
my ($command, $opt_argument) = @ARGV;

# Process given command from command line.
switch($command) {
	case "status" { &HandleStatus(); }

	case "block" { &HandleBlockUnblockCommand($command, $opt_argument); }
	case "unblock" { &HandleBlockUnblockCommand($command, $opt_argument); }

	case "flush" { &SendCommand("flush"); }
	case "reload" { &SendCommand("reload"); }
	case "reload-ignore-list" { &SendCommand("reload-ignore-list"); }
	case "logrotate" { &SendCommand("logrotate"); }

	# Print usage / help text.
	else {
		print "Guardian $version \n";
		print "Usage: guardianctrl <command> <optional arguments>\n";
		print " block <address>\tBlock the given IP-address.\n";
		print " unblock <address>\tUnblock the given IP-address.\n\n";

		print " flush\t\t\tUnblock/Flush all blocked IP-addresses.\n";
		print " status\t\t\tDisplay weather guardian is running and some details.\n\n";

		print " reload\t\t\tReload the configuration.\n";
		print " reload-ignore-list\tForce guardian to reload/regenerate it's ignore list.\n";
		print " logrotate\t\tTell guardian that the monitored files have been rotated by logrotate.\n";
	}
}

#
## The SendCommand function.
#
## This function is responsible for sending commands to guardian by using the provided
## client function from guardian's socket module. It also does a check if guardian has
## been launched, before trying to sent the desired command.
#
sub SendCommand ($) {
	my ($command) = @_;

	# Abort if no guardian instance is running.
	unless (&Guardian::Daemon::IsRunning()) {
		print STDERR "No running guardian instance found. Aborting!\n";
		return;
	}
		
	# Use the Socket client to transmitt the requested command to the daemon.
	&Guardian::Socket::Client($command);
}

#
## HandleBlockUnblockCommand function.
#
## This function mostly does the input validation for blocking and unblocking addresses
## before using the SendCommand() function to submit the desired command to the running
## guardian process.
#
sub HandleBlockUnblockCommand ($$) {;
	my ($command, $address) = @_;

	# Check if an address has been given.
	unless ($address) {
		print STDERR "No address has been given.\n";
		return;
	}

	# Check if the provided address is valid.
	# The called function will return 4 or 6 for the used IP-protocol
	# version if the address is valid.
	unless (&Guardian::Base::DetectIPProtocolVersion($address)) {
		print STDERR "$address is not a valid IPv4 nor IPv6 address.\n";
		return;
	}

	# Check if the given address is localhost.
	if (($address eq "127.0.0.1") || ($address eq "::1")) {
		print STDERR "$address is localhost and must not be blocked.\n";
		return;
	}

	# Check if block/unblock has been called.
	if (($command eq "block") || ($command eq "unblock")) {
		# Call subfunction to send the command through the socket.
		&SendCommand("$command $address");
	}
}

#
## HandleStatus function.
#
## This function just checks if guardian is running and will print some additional details.
#
sub HandleStatus () {
	# Check if guardian is running.
	unless (&Guardian::Daemon::IsRunning()) {
		print STDERR "Guardian is not running yet.\n";
		return;
	}

	# Grab process-id.
	my $pid = &Guardian::Daemon::GetPID();

	# Print out grabbed details.
	print "Guardian is running with process-id ($pid).\n";
}
