#! /usr/bin/perl -w 

# crontab-teil der die IP Adressen richtig einstellt. 
# aber jeweils die Zeitstempel prüft damit bei einer Änderung
# die Firewall umkonfiguriert wird
use strict; 

my $data_storage = "/var/run/squeezebox-firewall/ip-addr.conf";
my $timestamp    = "/var/run/squeezebox-firewall/last-run"; 

###############################################################
# Subroutinen
###############################################################
sub ReadConfig() {
    # Search the configuration file for the "per user" base in the homedir,
    # afterwards search it at the global position 
	if (! open(FH, "<", $data_storage)) {
		print STDERR "Error reading configuration file $data_storage: $!\n";
		exit(1);
	}
	my @FILEDATA = <FH>;
	chomp @FILEDATA;
	close(FH);
	my $srv;
	my %CONFIG;
	foreach my $read (@FILEDATA) {
		if ( $read =~ m/^#/ ) {
			next; # ignore comment lines
		}
		if ( $read =~ m/\[/ ) {
			$read =~ s/[\[\]\s]//g;
			$srv = $read;
		} elsif ($read =~ m/\=/) {
			$read =~ m/^\s*([\w\-.]+)\s*=\s*(.*)\s*$/; 
			my $key = $1; 
			my $value = $2; 
			$CONFIG{$srv}{$key} = $value;
		} else {
			# keine [], kein = Zeichen, ignorieren
			next;
		}
	}
	return \%CONFIG;
}

sub FlushRules() {
	system("iptables -F Squeezebox_Allow");
	return;
}


sub ForbidAll($) {
	# Alles andere verbieten
	my $ip = shift; 
	system("iptables -A Squeezebox_Allow -p tcp -d " . $ip . " --dport 3483 -j REJECT --reject-with tcp-reset");
	system("iptables -A Squeezebox_Allow -p tcp -d " . $ip . " --dport 9090 -j REJECT --reject-with tcp-reset"); 
	system("iptables -A Squeezebox_Allow -p tcp -d " . $ip . " --dport 9000 -j REJECT --reject-with tcp-reset");
	system("iptables -A Squeezebox_Allow -p udp -d " . $ip . " --dport 3483 -j REJECT");
	return; 
}

# Flag das sich merkt ob wir laufen müssen... 
my $need_run = 0;

# Okay.. lese die Zeitstempel der beiden Dateien ein.

my @TSD = stat $data_storage; 
if (! @TSD) {
	print STDERR "Cannot stat configuration file $data_storage: $!\n";
	exit(1); 
}
my $mtime_data_storage = $TSD[9];

my @TST = stat $timestamp; 

# Last Timestamp fehlt, wir müssen laufen
my $mtime_timestamp = $TST[9]; 
if (! defined $mtime_timestamp) {
	$need_run = 1; 
}

my $current_time = time();

#
if (defined $mtime_timestamp && $current_time - $mtime_data_storage > 87000) {
	print STDERR "Last touch of $data_storage was on " .localtime($mtime_data_storage) . ". This is too old. Firewalling all ports.\n"; 
	$need_run = 2; 

}

if (defined $mtime_data_storage && defined $mtime_timestamp && ($mtime_data_storage >= $mtime_timestamp)) {
	$need_run = 1; 
}

firewall: 
if ($need_run > 0) {
	# Read configuration file $data_storage 
	my $conf = ReadConfig(); 
	my $ip = $$conf{'config'}{'remote-ip'}; 
	my $user = $$conf{'config'}{'remote-user'}; 
	my $my_ip = $$conf{'config'}{'local-ip'}; 
	if (! defined $ip || $ip !~ /\d{1,3}\.\d{1,3}\.\d{1,3}.\d{1,3}/ ) {
		print STDERR "Sorry, $data_storage contains invalid remote-ip address $ip.\n";
		exit(1);
	}
	if (! defined $my_ip || $my_ip !~ /\d{1,3}\.\d{1,3}\.\d{1,3}.\d{1,3}/ ) {
		print STDERR "Sorry, $data_storage contains invalid remote-ip address $my_ip.\n";
		exit(1);
	}
	FlushRules();
	if ($need_run == 1) {
		print STDERR "Setting up firewall rules for Squeezebox clients in NATed Network [$ip]\n";
		#  Client von ALLOWEDREMOTEIP erlauben
		system("iptables -A Squeezebox_Allow -p tcp -d $my_ip -s $ip --dport 9000 -j ACCEPT");
		system("iptables -A Squeezebox_Allow -p tcp -d $my_ip -s $ip --dport 9090 -j ACCEPT");
		system("iptables -A Squeezebox_Allow -p tcp -d $my_ip -s $ip --dport 3483 -j ACCEPT"); 
		system("iptables -A Squeezebox_Allow -p udp -d $my_ip -s $ip --dport 3483 -j ACCEPT"); 
	}
	ForbidAll($my_ip);
	open(FH, ">", $timestamp) || die "Sorry, cannot write timestamp-file $timestamp: $!\n"; 
	close(FH); 
}
exit(0); 
