diff -r 000000000000 -r 26a429d60aae insertRules --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/insertRules Sat Oct 11 20:18:44 2008 +0000 @@ -0,0 +1,159 @@ +#! /usr/bin/perl +# $Id$ +# $URL$ +# © 2008 Heiko Schlittermann +use constant USAGE => <<'#'; +{{ME}} [-n] [-v] +# + +use strict; +use warnings; +use File::Basename; +use AppConfig; + +use constant ME => basename $0; + +#use constant FI => { chain => "ipac~fi", parent => "FORWARD", iface => "--out" }; +#use constant FO => { chain => "ipac~fo", parent => "FORWARD", iface =>"--in" }; +#use constant I => { chain => "ipac~i", parent => "OUTPUT", iface => "--in" }; +#use constant O => { chain => "ipac~o", parent => "INPUT", iface => "--out" }; + +my %TARGETS = ( + "ipac~fi" => { chain => "ipac~fi", parent => "FORWARD", iface => "--in-interface" }, + "ipac~fo" => { chain => "ipac~fo", parent => "FORWARD", iface => "--out-interface" }, + "ipac~i" => { chain => "ipac~i", parent => "OUTPUT", iface => "--out-interface" }, + "ipac~o" => { chain => "ipac~o", parent => "INPUT", iface => "--in-interface" }, +); + +use constant FILE => $ENV{IPAC_RULES} ? $ENV{IPAC_RULES} : "/etc/ipac-ng/rules.conf"; + +use constant CONFIG => ( + { CASE => 1 }, + nothing => { ARGS => "!", DEFAULT => 0 }, + verbose => { ARGS => "!", DEFAULT => 0 }, +); + +my $Cf = new AppConfig CONFIG or die; + $Cf->getopt or die; + +sub checkTarget($); +sub insertTarget($); +sub cleanTarget($); +sub parseConfig($); +sub expand($); + +MAIN: { + my @cmds; + + # Check, if our rules exist + foreach (keys %TARGETS) { + checkTarget($TARGETS{$_}) + or push @cmds, insertTarget($TARGETS{$_}); + + push @cmds, cleanTarget($TARGETS{$_}); + } + + + my ($iptables, $rules) = parseConfig(FILE); + push @cmds, @$iptables; + + + foreach (@cmds) { + print "@$_\n" if $Cf->verbose or $Cf->nothing; + next if $Cf->nothing; + system @$_ and do { + warn "FAILED: @$_\n" if not $Cf->verbose; + }; + } + + if (!$Cf->nothing) { + open(RUNFILE, $_ = ">/var/run/ipac.rules") or die "Can't open $_: $!\n"; + print RUNFILE join "\n", @$rules; + close(RUNFILE); + } +} + +{ + my $dump; +sub checkTarget($) { + my $target = shift; + + if (!$dump) { + open(X, "iptables-save|") or die "Can't open iptables-save: $!\n"; + $dump = join "", grep /^:/, ; + close(X); + } + + return $dump =~ /^:$target->{chain}/m + +} } + +sub insertTarget($) { + my $target = shift; + + return ( + ["iptables", "--new-chain" => $target->{chain}], + ["iptables", + "--insert" => $target->{parent}, + "--jump" => $target->{chain}] + ); +} + +sub cleanTarget($) { + my $target = shift; + return ["iptables", + "--flush" => $target->{chain}]; +} + +sub parseConfig($) { + my (@iptables, @rules); + my $file = shift; + local(@ARGV) = ($file); + + die ME.": Can't open $file: $!\n" if not -r $file; + + @ARGV = ($file); + + # Read the config file and create the iptables statements + while (<>) { + s/#.*//; + s/^\s*$//; + next unless $_; + + chomp; + + + my (%src, %dst); + (my ($name, $target, $iface, $proto), $src{ip}, $dst{ip}) + = split /\s*\|\s*/, $_; + + # $src / $dst + foreach (\%src, \%dst) { + @{$_}{qw/ip port/} = split /[:\s]/, $_->{ip}; + } + + + my @cmd = ("iptables", + "--append" => $target, + $TARGETS{$target}->{iface} => $iface, + "--src" => expand($src{ip}), + "--dst" => expand($dst{ip}), + "--proto" => expand($proto), + $src{port} ? ("--sport" => $src{port}) : (), + $dst{port} ? ("--dport" => $dst{port}) : (), + ); + + push @iptables, \@cmd; + push @rules, "$target|$name"; + } + + return \@iptables, \@rules; +} + +sub expand($) { + local $_ = shift; + return ($_) if not /^!/; + return ("!", substr($_, 1)); +} + +# vim:sts=4 sw=4 aw ai sm: