#!/usr/bin/perl

use strict;

use Getopt::Long;

my $clear = 0;
my $config = "hosts";
my $help = 0;
my $noaodv = 0;
my $oldin = 0;
my $oldout = 0;
my $debug = 0;
my $matchdebug = 0;
my $alldebug = 0;
my $hello = 0;

GetOptions(
	"config=s" => \$config,
	"clear" => \$clear,
	"noaodv" => \$noaodv,
	"oldin" => \$oldin,
	"oldout" => \$oldout,
	"hello=i" => \$hello,
	"debug" => \$debug,
	"matchdebug" => \$matchdebug,
	"alldebug" => \$alldebug,
	"help" => \$help,
) or die ("Error parsing options: $!");

if($help){
	print "Usage: rulesetup [--config <configfile>] [--clear] [--noaodv] [--matchdebug] [--alldebug] [--hello <n'th>]\n";
	exit 0;
}

open(CONFIG,$config) || die ("Could not open $config: $!");


if($matchdebug && ! $alldebug){
	$matchdebug = "--matchdebug";
}else{
	$matchdebug = "";
}

if($alldebug){
	$alldebug = "--alldebug";
}else{
	$alldebug = "";
}

my $debugopt = "$alldebug $matchdebug";

my @connection;
my %hosts;
my $admin;
my $wlanprefix;
while(<CONFIG>){
	chomp;
	if(/^connection/){
		s/^connection\s*=//;
		@connection = split /-/;
	}else{
		s/\s*//g;
		my @line = split /=/;
		if($line[0] =~ /admin/){
			$admin = $line[1];
		}else{
			if($line[0] =~ /prefix/){
				$wlanprefix = $line[1];
			}else{
				$hosts{$line[0]} = $line[1];
			}
		}
	}
}
close(CONFIG);
if($clear){
	print "Removing rules...\n";
}
for (my $i = 0; $i <= $#connection; $i++){
	print "$i: Working with $connection[$i]\n";
	my $cur = $connection[$i];
	if(!$clear){
		my $left = my $right = "";
		if($i > 0){
			$left = $connection[$i-1];
		}
		if ($i < $#connection){
			$right = $connection[$i+1];
		}
		# Clear old rules first
		clear($cur);
		# Allow ssh from everywhere
		system("ssh root@".$cur." iptables -A INPUT -i eth0 -p tcp --sport ssh -s $admin -j ACCEPT");
		system("ssh root@".$cur." iptables -A INPUT -i eth0 -p tcp --dport ssh -s $admin -j ACCEPT");
		system("ssh root@".$cur." iptables -A OUTPUT -o eth0 -p tcp --sport ssh -d $admin -j ACCEPT");
		system("ssh root@".$cur." iptables -A OUTPUT -o eth0 -p tcp --dport ssh -d $admin -j ACCEPT");
		# Allow loopback communication
		system("ssh root@".$cur." iptables -A INPUT -i lo -j ACCEPT");
		system("ssh root@".$cur." iptables -A OUTPUT -o lo -j ACCEPT");
		# Redirect aodv packets
		if(!$noaodv){
			system("ssh root@".$cur." modprobe ip_queue");
			if($oldin){
				if($left){
					if($debug){
						system("ssh root@".$cur." iptables -A INPUT -p udp --dport 654 -m mac --mac-source ".$hosts{$left}." -j LOG --log-prefix 'Queue: '");
					}
					system("ssh root@".$cur." iptables -A INPUT -p udp --dport 654 -m mac --mac-source ".$hosts{$left}." -j QUEUE");
				}
				if($right){
					if($debug){
						system("ssh root@".$cur." iptables -A INPUT -p udp --dport 654 -m mac --mac-source ".$hosts{$right}." -j LOG --log-prefix 'Queue: '");
					}
					system("ssh root@".$cur." iptables -A INPUT -p udp --dport 654 -m mac --mac-source ".$hosts{$right}." -j QUEUE");
				}
			}else{
				if($left){
					if($debug){
						system("ssh root@".$cur." iptables -A INPUT -p udp --dport 654 -m mac --mac-source ".$hosts{$left}." -m aodvext --aodvext -j LOG --log-prefix 'Queue: '");
					}
					system("ssh root@".$cur." iptables -A INPUT -p udp --dport 654 -m mac --mac-source ".$hosts{$left}." -m aodvext --aodvext $debugopt -j QUEUE");
				}
				if($right){
					if($debug){
						system("ssh root@".$cur." iptables -A INPUT -p udp --dport 654 -m mac --mac-source ".$hosts{$right}." -m aodvext --aodvext -j LOG --log-prefix 'Queue: '");
					}
					system("ssh root@".$cur." iptables -A INPUT -p udp --dport 654 -m mac --mac-source ".$hosts{$right}." -m aodvext --aodvext $debugopt -j QUEUE");
				}
			}
			if($oldout){
				if($debug){
					system("ssh root@".$cur." iptables -A OUTPUT -p udp --dport 654 -j LOG --log-prefix 'Queue: '");
				}
				system("ssh root@".$cur." iptables -A OUTPUT -p udp --dport 654 -j QUEUE");
			}else{
				if($debug){
					system("ssh root@".$cur." iptables -A OUTPUT -p udp --dport 654 -m aodvext --switcher --hello $hello -j LOG --log-prefix 'Queue: '");
				}
				system("ssh root@".$cur." iptables -A OUTPUT -p udp --dport 654 -m aodvext --switcher --hello $hello $debugopt -j QUEUE");
			}
		}
		if($left){
			# Accept packets from left neighbour, who also accepts ours
			if($debug){
				system("ssh root@".$cur." iptables -A INPUT -i eth1 -m mac --mac-source ".$hosts{$left}." -j LOG --log-prefix 'Accept: '");
			}
			system("ssh root@".$cur." iptables -A INPUT -i eth1 -m mac --mac-source ".$hosts{$left}." -j ACCEPT");
		}
		if($right){
			# Accept packets from right neighbour, who also accepts ours
			if($debug){
				system("ssh root@".$cur." iptables -A INPUT -i eth1 -m mac --mac-source ".$hosts{$right}." -j LOG --log-prefix 'Accept: '");
			}
			system("ssh root@".$cur." iptables -A INPUT -i eth1 -m mac --mac-source ".$hosts{$right}." -j ACCEPT");
		}
		# Acce[t packets originating from host himself
		my $hostnum = $cur;
		$hostnum =~ s/\D*//;
		system("ssh root@".$cur." iptables -A INPUT -i eth1 --source $wlanprefix.$hostnum --destination 255.255.255.255  -j ACCEPT");

		if($debug){
			# Log packets which are going to be dropped
			system("ssh root@".$cur." iptables -A INPUT -j LOG --log-prefix 'Drop: '");
			# and outgoing aodv-packets with extension
			system("ssh root@".$cur." iptables -A OUTPUT -p udp --dport 654 -m aodvext --aodvext -j LOG --log-prefix 'Out: '");
			# Log all forwards
			system("ssh root@".$cur." iptables -A FORWARD -j LOG --log-prefix 'Fwd: '");
		}
		# By default, accept no input
		system("ssh root@".$cur." iptables -P INPUT DROP");
	}else{
		clear($cur);
	}
}

sub clear(){
	my $host = shift;
	system("ssh root@".$host." iptables -P INPUT ACCEPT");
	system("ssh root@".$host." iptables -F");

}
