#!/usr/bin/perl -w

# 20040709	mroth@netlabs.ch && remo.ryter@gmx.net 
# File:		iptables_t
# Version:	1.0 
# Group:	sysman, security
# Legal:   	GPL 
# Usage:	at will ;) - check iptables_t -h
# Purpose:	wrapperscript to iptables for rules
#			with expiration time (the rules will be
#			removed after expiration)
# EdHist:
# 20040707	0.9	initial release 
# 20040709	1.0 first public release	

### START CONFIG SECTION ###

# the location of the iptables program
$iptables_cmd='/usr/sbin/iptables';

#### END CONFIG SECTION ####

# check if the program is in place
die "$iptables_cmd: $!\n" if (! -f $iptables_cmd);

# add every element from the @ARGV array to the
# @args array without the -T flag and its parameter.
# in the same turn the expiration ($time)
# parameter will be initialized 
@args = grep {

	# check if the current element is the -T flag
	# if Yes set the found flag to 1.
	# this expression has the value 1 but will be
	# negotiated with the ! so that the -T parmeter
	# isn't included in the @args array
	!(/^-T$/ && ($found=1) ||			

	# if the prior element was the -T flag,
	# set the $time variable to the value
	# of the current element.
	# reset the $found value and don't add
	# this element to @args
	$found && ($time=$_) && !($found=0) ||

	# if its not the flag nor the parameter
	# add this element to @args
	0)

 } @ARGV; # command line arguments

# check if the argument (if there is one) is numeric
if($time && $time!~m/^[0-9]+$/) {
	print STDERR "invalid argument, please check iptables_t -h\n";
	exit(1);
}

# check if a -h or --help argument was given on the
# command line and add our _usage_ message to the
# top of the help message from iptables 
if(scalar(grep { /^-h$/ || /^--help$/ } @args)) {
	print "iptables_t WrapperScript for rules with expiration\n";
	print "Usage: iptables_t [-T] time\n";
	print "Commands: -T time\t";
	print "set the expiration time in seconds for this rule\n";
	print "-"x20 . "end wrapper script" . "-"x20 . "\n";

	# execute the command and never return (no fork is done).
	# if the command fails, die will print the appropriate error msg.
	!exec($iptables_cmd, @args) || exit(1);
}

# run the iptables command with the contributed arguments (with fork ;-)
!system($iptables_cmd, @args) || exit(1);

# there's no further processing necessari if we don't have a time parameter
exit(0) if(!$time);

# reset the $found variable, we will use it to check if a
# '-A' == APPEND parameter was in the iptables arguments.
# '-A' will be replaced by '-D' to remove the rule
$found=0;
grep { /^-A$/ && ($_='-D') && ($found=1) || 1 } @args;

# if we don't found a -A parameter we don't
# know how to handle this rule
if(!$found) {
	print "sorry, don't know how to remove this rule!\n";
	print "it will stay in place!\n";
	exit(1);
}

# fork off a chlid process which will handle
# the rule removal. the parent process just exits
if(($pid=fork())==0) { # child process

	# sleep until we have to remove the rule
	sleep($time);

	# remove the rule and never return...
	!exec($iptables_cmd, @args) || exit(1);

# if fork fails
} elsif($pid<1) {
	die "fork() failed: $!\n";
} 
