Break out rule processing into a module

git-svn-id: https://shorewall.svn.sourceforge.net/svnroot/shorewall/trunk@5542 fbd18981-670d-0410-9b5c-8dc0c1a9a2bb
This commit is contained in:
teastep 2007-03-15 03:17:56 +00:00
parent 24f61c69c7
commit b54ea15e2e
2 changed files with 466 additions and 448 deletions

465
New/Shorewall/Rules.pm Normal file
View File

@ -0,0 +1,465 @@
package Shorewall::Rules;
require Exporter;
use Shorewall::Common;
use Shorewall::Config;
use Shorewall::Zones;
use Shorewall::Chains;
use Shorewall::Actions;
use Shorewall::Macros;
use strict;
our @ISA = qw(Exporter);
our @EXPORT = qw( process_rules );
our @EXPORT_OK = qw( process_rule process_rule1 );
our @VERSION = 1.00;
#
# Set to one if we find a SECTION
#
my $sectioned = 0;
sub process_rule1 ( $$$$$$$$$ );
#
# Expand a macro rule from the rules file
#
sub process_macro ( $$$$$$$$$$$ ) {
my ($macrofile, $target, $param, $source, $dest, $proto, $ports, $sports, $origdest, $rate, $user) = @_;
my $standard = ( $macrofile =~ /^($env{SHAREDIR})/ );
progress_message "..Expanding Macro $macrofile...";
open M, $macrofile or fatal_error "Unable to open $macrofile: $!";
while ( $line = <M> ) {
chomp $line;
next if $line =~ /^\s*#/;
next if $line =~ /^\s*$/;
$line =~ s/\s+/ /g;
$line =~ s/#.*$//;
$line = expand_shell_variables $line unless $standard;
my ( $mtarget, $msource, $mdest, $mproto, $mports, $msports, $mrate, $muser ) = split /\s+/, $line;
$mtarget = merge_levels $target, $mtarget;
if ( $mtarget =~ /^PARAM:?/ ) {
fatal_error 'PARAM requires that a parameter be supplied in macro invocation' unless $param;
$mtarget = substitute_action $param, $mtarget;
}
my $action = isolate_basic_target $mtarget;
my $actiontype = $targets{$action};
if ( $actiontype & ACTION ) {
unless ( $usedactions{$action} ) {
createactionchain $mtarget;
$usedactions{$mtarget} = 1;
}
$mtarget = find_logactionchain $mtarget;
} else {
fatal_error "Invalid Action ($mtarget) in rule \"$line\"" unless $actiontype & STANDARD;
}
if ( $msource ) {
if ( ( $msource eq '-' ) || ( $msource eq 'SOURCE' ) ) {
$msource = $source || '';
} elsif ( $msource eq 'DEST' ) {
$msource = $dest || '';
} else {
$msource = merge_macro_source_dest $msource, $source;
}
} else {
$msource = '';
}
$msource = '' if $msource eq '-';
if ( $mdest ) {
if ( ( $mdest eq '-' ) || ( $mdest eq 'DEST' ) ) {
$mdest = $dest || '';
} elsif ( $mdest eq 'SOURCE' ) {
$mdest = $source || '';
} else {
$mdest = merge_macro_source_dest $mdest, $dest;
}
} else {
$mdest = '';
}
$mdest = '' if $mdest eq '-';
$mproto = merge_macro_column $mproto, $proto;
$mports = merge_macro_column $mports, $ports;
$msports = merge_macro_column $msports, $sports;
$mrate = merge_macro_column $mrate, $rate;
$muser = merge_macro_column $muser, $user;
process_rule1 $mtarget, $msource, $mdest, $mproto, $mports, $msports, $origdest, $rate, $user;
progress_message " Rule \"$line\" $done"; }
close M;
progress_message '..End Macro'
}
#
# Once a rule has been completely resolved by macro expansion, it is processed by this function.
#
sub process_rule1 ( $$$$$$$$$ ) {
my ( $target, $source, $dest, $proto, $ports, $sports, $origdest, $ratelimit, $user ) = @_;
my ( $action, $loglevel) = split_action $target;
my $rule = '';
my $actionchainref;
$ports = '' unless defined $ports;
$sports = '' unless defined $sports;
$origdest = '' unless defined $origdest;
$ratelimit = '' unless defined $ratelimit;
$user = '' unless defined $user;
#
# Determine the validity of the action
#
my $actiontype = $targets{$action} || find_macro( isolate_basic_target $action );
fatal_error "Unknown action ($action) in rule \"$line\"" unless $actiontype;
if ( $actiontype == MACRO ) {
process_macro
$macros{isolate_basic_target $action}, $
target ,
(split '/', $action)[1] ,
$source,
$dest,
$proto,
$ports,
$sports,
$origdest,
$ratelimit,
$user;
return;
}
#
# We can now dispense with the postfix characters
#
$action =~ s/[\+\-!]$//;
#
# Mark target as used
#
if ( $actiontype & ACTION ) {
unless ( $usedactions{$target} ) {
$usedactions{$target} = 1;
createactionchain $target;
}
}
#
# Take care of irregular syntax and targets
#
if ( $actiontype & REDIRECT ) {
if ( $dest eq '-' ) {
$dest = "$firewall_zone";
} else {
$dest = "$firewall_zone" . '::' . "$dest";
}
} elsif ( $action eq 'REJECT' ) {
$action = 'reject';
} elsif ( $action eq 'CONTINUE' ) {
$action = 'RETURN';
}
#
# Isolate and validate source and destination zones
#
my $sourcezone;
my $destzone;
if ( $source =~ /^(.+?):(.*)/ ) {
$sourcezone = $1;
$source = $2;
} else {
$sourcezone = $source;
$source = ALLIPv4;
}
if ( $dest =~ /^(.+?):(.*)/ ) {
$destzone = $1;
$dest = $2;
} else {
$destzone = $dest;
$dest = ALLIPv4;
}
fatal_error "Unknown source zone ($sourcezone) in rule \"$line\"" unless $zones{$sourcezone};
fatal_error "Unknown destination zone ($destzone) in rule \"$line\"" unless $zones{$destzone};
#
# Take care of chain
#
my $chain = "${sourcezone}2${destzone}";
my $chainref = ensure_filter_chain $chain, 1;
#
# Validate Policy
#
my $policy = $chainref->{policy};
fatal_error "No policy defined from $sourcezone to zone $destzone" unless $policy;
fatal_error "Rules may not override a NONE policy: rule \"$line\"" if $policy eq 'NONE';
#
# Generate Fixed part of the rule
#
$rule = do_proto $proto, $ports, $sports . do_ratelimit( $ratelimit ) . ( do_user $user );
$origdest = ALLIPv4 unless $origdest and $origdest ne '-';
#
# Generate NAT rule(s), if any
#
if ( $actiontype & NATRULE ) {
my ( $server, $serverport , $natchain );
fatal_error "$target rules not allowed in the $section SECTION" if $section ne 'NEW';
#
# Isolate server port
#
if ( $dest =~ /^(.*)(:(\d+))$/ ) {
$server = $1;
$serverport = $3;
} else {
$server = $dest;
$serverport = '';
}
#
# After DNAT, dest port will be the server port
#
$ports = $serverport if $serverport;
fatal_error "A server must be specified in the DEST column in $action rules: \"$line\"" unless ( $actiontype & REDIRECT ) || $server;
fatal_error "Invalid server ($server), rule: \"$line\"" if $server =~ /:/;
#
# Generate the target
#
my $target = '';
if ( $action eq 'SAME' ) {
fatal_error 'Port mapping not allowed in SAME rules' if $serverport;
$target = '-j SAME ';
for my $serv ( split /,/, $server ) {
$target .= "--to $serv ";
}
$serverport = $ports;
} elsif ( $action eq ' -j DNAT' ) {
$serverport = ":$serverport" if $serverport;
for my $serv ( split /,/, $server ) {
$target .= "--to ${serv}${serverport} ";
}
} else {
$target = '-j REDIRECT --to-port ' . ( $serverport ? $serverport : $ports );
}
#
# And generate the nat table rule(s)
#
expand_rule
ensure_chain ('nat' , $zones{$sourcezone}{type} eq 'firewall' ? 'OUTPUT' : dnat_chain $sourcezone ) ,
$rule ,
$source ,
$origdest ,
'' ,
$target ,
$loglevel ,
$action ,
$serverport ? do_proto( $proto, '', '' ) : '';
#
# After NAT, the destination port will be the server port; Also, we log NAT rules in the nat table rather than in the filter table.
#
unless ( $actiontype & NATONLY ) {
$rule = do_proto $proto, $ports, $sports . do_ratelimit( $ratelimit ) . do_user $user;
$loglevel = '';
}
} elsif ( $actiontype & NONAT ) {
#
# NONAT or ACCEPT+ -- May not specify a destination interface
#
fatal_error "Invalid DEST ($dest) in $action rule \"$line\"" if $dest =~ /:/;
expand_rule
ensure_chain ('nat' , $zones{$sourcezone}{type} eq 'firewall' ? 'OUTPUT' : dnat_chain $sourcezone) ,
$rule ,
$source ,
$dest ,
'' ,
'-j RETURN ' ,
$loglevel ,
$action ,
'';
}
#
# Add filter table rule, unless this is a NATONLY rule type
#
unless ( $actiontype & NATONLY ) {
if ( $actiontype & ACTION ) {
$action = (find_logactionchain $target)->{name};
$loglevel = '';
}
expand_rule
ensure_chain ('filter', $chain ) ,
$rule ,
$source ,
$dest ,
$origdest ,
"-j $action " ,
$loglevel ,
$action ,
'';
}
}
#
# Process a Record in the rules file
#
sub process_rule ( $$$$$$$$$ ) {
my ( $target, $source, $dest, $proto, $ports, $sports, $origdest, $ratelimit, $user ) = @_;
my $intrazone = 0;
my $includesrcfw = 1;
my $includedstfw = 1;
my $optimize = $config{OPTIMIZE};
my $thisline = $line;
#
# Section Names are optional so once we get to an actual rule, we need to be sure that
# we close off any missing sections.
#
unless ( $sectioned ) {
finish_section 'ESTABLISHED,RELATED';
$section = 'NEW';
$sectioned = 1;
}
#
# Handle Wildcards
#
if ( $source =~ /^all[-+]/ ) {
if ( $source eq 'all+' ) {
$source = 'all';
$intrazone = 1;
} elsif ( ( $source eq 'all+-' ) || ( $source eq 'all-+' ) ) {
$source = 'all';
$intrazone = 1;
$includesrcfw = 0;
} elsif ( $source eq 'all-' ) {
$source = 'all';
$includesrcfw = 0;
}
}
if ( $dest =~ /^all[-+]/ ) {
if ( $dest eq 'all+' ) {
$dest = 'all';
$intrazone = 1;
} elsif ( ( $dest eq 'all+-' ) || ( $dest eq 'all-+' ) ) {
$dest = 'all';
$intrazone = 1;
$includedstfw = 0;
} elsif ( $source eq 'all-' ) {
$dest = 'all';
$includedstfw = 0;
}
}
my $action = isolate_basic_target $target;
$optimize = 0 if $action =~ /!^/;
if ( $source eq 'all' ) {
for my $zone ( @zones ) {
if ( $includesrcfw || ( $zones{$zone}{type} ne 'firewall' ) ) {
if ( $dest eq 'all' ) {
for my $zone1 ( @zones ) {
if ( $includedstfw || ( $zones{$zone1}{type} ne 'firewall' ) ) {
if ( $intrazone || ( $zone ne $zone1 ) ) {
my $policychainref = $filter_table->{"${zone}2${zone1}"}{policychain};
fatal_error "No policy from zone $zone to zone $zone1" unless $policychainref;
if ( ( ( my $policy ) = $policychainref->{policy} ) ne 'NONE' ) {
if ( $optimize > 0 ) {
my $loglevel = $policychainref->{loglevel};
if ( $loglevel ) {
next if $target eq "${policy}:$loglevel}";
} else {
next if $action eq $policy;
}
}
process_rule1 $target, $zone, $zone1 , $proto, $ports, $sports, $origdest, $ratelimit, $user;
}
}
}
}
} else {
process_rule1 $target, $zone, $dest , $proto, $ports, $sports, $origdest, $ratelimit, $user;
}
}
}
} elsif ( $dest eq 'all' ) {
for my $zone1 ( @zones ) {
my $zone = ( split /:/, $source )[0];
if ( ( $includedstfw || ( $zones{$zone1}{type} ne 'firewall') ) &&( ( $zone ne $zone1 ) || $intrazone) ) {
process_rule1 $target, $source, $zone1 , $proto, $ports, $sports, $origdest, $ratelimit, $user;
}
}
} else {
process_rule1 $target, $source, $dest, $proto, $ports, $sports, $origdest, $ratelimit, $user;
}
progress_message " Rule \"$thisline\" $done";
}
#
# Process the Rules File
#
sub process_rules() {
open RULES, "$ENV{TMP_DIR}/rules" or fatal_error "Unable to open stripped rules file: $!";
while ( $line = <RULES> ) {
chomp $line;
$line =~ s/\s+/ /g;
my ( $target, $source, $dest, $proto, $ports, $sports, $origdest, $ratelimit, $user, $extra ) = split /\s+/, $line;
if ( $target eq 'COMMENT' ) {
if ( $capabilities{COMMENTS} ) {
( $comment = $line ) =~ s/^\s*COMMENT\s*//;
$comment =~ s/\s*$//;
} else {
warning_message "COMMENT ignored -- requires comment support in iptables/Netfilter";
}
} elsif ( $target eq 'SECTION' ) {
fatal_error "Invalid SECTION $source" unless defined $sections{$source};
fatal_error "Duplicate or out of order SECTION $source" if $sections{$source};
fatal_error "Invalid Section $source $dest" if $dest;
$sectioned = 1;
$sections{$source} = 1;
if ( $section eq 'RELATED' ) {
$sections{ESTABLISHED} = 1;
finish_section 'ESTABLISHED';
} elsif ( $section eq 'NEW' ) {
@sections{'ESTABLISHED','RELATED'} = ( 1, 1 );
finish_section ( ( $section eq 'RELATED' ) ? 'RELATED' : 'ESTABLISHED,RELATED' );
}
$section = $source;
} else {
fatal_error "Invalid rules file entry: \"$line\"" if $extra;
process_rule $target, $source, $dest, $proto, $ports, $sports, $origdest, $ratelimit, $user;
}
}
close RULES;
$comment = '';
$section = 'DONE';
}
1;

View File

@ -16,11 +16,7 @@ use Shorewall::Policy;
use Shorewall::Macros;
use Shorewall::Actions;
use Shorewall::Accounting;
#
# Set to one if we find a SECTION
#
my $sectioned = 0;
use Shorewall::Rules;
sub process_tos() {
my $chain = 'pretos';
@ -486,449 +482,6 @@ sub setup_mac_lists( $ ) {
}
}
sub process_rule1 ( $$$$$$$$$ );
#
# Expand a macro rule from the rules file
#
sub process_macro ( $$$$$$$$$$$ ) {
my ($macrofile, $target, $param, $source, $dest, $proto, $ports, $sports, $origdest, $rate, $user) = @_;
my $standard = ( $macrofile =~ /^($env{SHAREDIR})/ );
progress_message "..Expanding Macro $macrofile...";
open M, $macrofile or fatal_error "Unable to open $macrofile: $!";
while ( $line = <M> ) {
chomp $line;
next if $line =~ /^\s*#/;
next if $line =~ /^\s*$/;
$line =~ s/\s+/ /g;
$line =~ s/#.*$//;
$line = expand_shell_variables $line unless $standard;
my ( $mtarget, $msource, $mdest, $mproto, $mports, $msports, $mrate, $muser ) = split /\s+/, $line;
$mtarget = merge_levels $target, $mtarget;
if ( $mtarget =~ /^PARAM:?/ ) {
fatal_error 'PARAM requires that a parameter be supplied in macro invocation' unless $param;
$mtarget = substitute_action $param, $mtarget;
}
my $action = isolate_basic_target $mtarget;
my $actiontype = $targets{$action};
if ( $actiontype & ACTION ) {
unless ( $usedactions{$action} ) {
createactionchain $mtarget;
$usedactions{$mtarget} = 1;
}
$mtarget = find_logactionchain $mtarget;
} else {
fatal_error "Invalid Action ($mtarget) in rule \"$line\"" unless $actiontype & STANDARD;
}
if ( $msource ) {
if ( ( $msource eq '-' ) || ( $msource eq 'SOURCE' ) ) {
$msource = $source || '';
} elsif ( $msource eq 'DEST' ) {
$msource = $dest || '';
} else {
$msource = merge_macro_source_dest $msource, $source;
}
} else {
$msource = '';
}
$msource = '' if $msource eq '-';
if ( $mdest ) {
if ( ( $mdest eq '-' ) || ( $mdest eq 'DEST' ) ) {
$mdest = $dest || '';
} elsif ( $mdest eq 'SOURCE' ) {
$mdest = $source || '';
} else {
$mdest = merge_macro_source_dest $mdest, $dest;
}
} else {
$mdest = '';
}
$mdest = '' if $mdest eq '-';
$mproto = merge_macro_column $mproto, $proto;
$mports = merge_macro_column $mports, $ports;
$msports = merge_macro_column $msports, $sports;
$mrate = merge_macro_column $mrate, $rate;
$muser = merge_macro_column $muser, $user;
process_rule1 $mtarget, $msource, $mdest, $mproto, $mports, $msports, $origdest, $rate, $user;
progress_message " Rule \"$line\" $done"; }
close M;
progress_message '..End Macro'
}
#
# Once a rule has been completely resolved by macro expansion, it is processed by this function.
#
sub process_rule1 ( $$$$$$$$$ ) {
my ( $target, $source, $dest, $proto, $ports, $sports, $origdest, $ratelimit, $user ) = @_;
my ( $action, $loglevel) = split_action $target;
my $rule = '';
my $actionchainref;
$ports = '' unless defined $ports;
$sports = '' unless defined $sports;
$origdest = '' unless defined $origdest;
$ratelimit = '' unless defined $ratelimit;
$user = '' unless defined $user;
#
# Determine the validity of the action
#
my $actiontype = $targets{$action} || find_macro( isolate_basic_target $action );
fatal_error "Unknown action ($action) in rule \"$line\"" unless $actiontype;
if ( $actiontype == MACRO ) {
process_macro
$macros{isolate_basic_target $action}, $
target ,
(split '/', $action)[1] ,
$source,
$dest,
$proto,
$ports,
$sports,
$origdest,
$ratelimit,
$user;
return;
}
#
# We can now dispense with the postfix characters
#
$action =~ s/[\+\-!]$//;
#
# Mark target as used
#
if ( $actiontype & ACTION ) {
unless ( $usedactions{$target} ) {
$usedactions{$target} = 1;
createactionchain $target;
}
}
#
# Take care of irregular syntax and targets
#
if ( $actiontype & REDIRECT ) {
if ( $dest eq '-' ) {
$dest = "$firewall_zone";
} else {
$dest = "$firewall_zone" . '::' . "$dest";
}
} elsif ( $action eq 'REJECT' ) {
$action = 'reject';
} elsif ( $action eq 'CONTINUE' ) {
$action = 'RETURN';
}
#
# Isolate and validate source and destination zones
#
my $sourcezone;
my $destzone;
if ( $source =~ /^(.+?):(.*)/ ) {
$sourcezone = $1;
$source = $2;
} else {
$sourcezone = $source;
$source = ALLIPv4;
}
if ( $dest =~ /^(.+?):(.*)/ ) {
$destzone = $1;
$dest = $2;
} else {
$destzone = $dest;
$dest = ALLIPv4;
}
fatal_error "Unknown source zone ($sourcezone) in rule \"$line\"" unless $zones{$sourcezone};
fatal_error "Unknown destination zone ($destzone) in rule \"$line\"" unless $zones{$destzone};
#
# Take care of chain
#
my $chain = "${sourcezone}2${destzone}";
my $chainref = ensure_filter_chain $chain, 1;
#
# Validate Policy
#
my $policy = $chainref->{policy};
fatal_error "No policy defined from $sourcezone to zone $destzone" unless $policy;
fatal_error "Rules may not override a NONE policy: rule \"$line\"" if $policy eq 'NONE';
#
# Generate Fixed part of the rule
#
$rule = do_proto $proto, $ports, $sports . do_ratelimit( $ratelimit ) . ( do_user $user );
$origdest = ALLIPv4 unless $origdest and $origdest ne '-';
#
# Generate NAT rule(s), if any
#
if ( $actiontype & NATRULE ) {
my ( $server, $serverport , $natchain );
fatal_error "$target rules not allowed in the $section SECTION" if $section ne 'NEW';
#
# Isolate server port
#
if ( $dest =~ /^(.*)(:(\d+))$/ ) {
$server = $1;
$serverport = $3;
} else {
$server = $dest;
$serverport = '';
}
#
# After DNAT, dest port will be the server port
#
$ports = $serverport if $serverport;
fatal_error "A server must be specified in the DEST column in $action rules: \"$line\"" unless ( $actiontype & REDIRECT ) || $server;
fatal_error "Invalid server ($server), rule: \"$line\"" if $server =~ /:/;
#
# Generate the target
#
my $target = '';
if ( $action eq 'SAME' ) {
fatal_error 'Port mapping not allowed in SAME rules' if $serverport;
$target = '-j SAME ';
for my $serv ( split /,/, $server ) {
$target .= "--to $serv ";
}
$serverport = $ports;
} elsif ( $action eq ' -j DNAT' ) {
$serverport = ":$serverport" if $serverport;
for my $serv ( split /,/, $server ) {
$target .= "--to ${serv}${serverport} ";
}
} else {
$target = '-j REDIRECT --to-port ' . ( $serverport ? $serverport : $ports );
}
#
# And generate the nat table rule(s)
#
expand_rule
ensure_chain ('nat' , $zones{$sourcezone}{type} eq 'firewall' ? 'OUTPUT' : dnat_chain $sourcezone ) ,
$rule ,
$source ,
$origdest ,
'' ,
$target ,
$loglevel ,
$action ,
$serverport ? do_proto( $proto, '', '' ) : '';
#
# After NAT, the destination port will be the server port; Also, we log NAT rules in the nat table rather than in the filter table.
#
unless ( $actiontype & NATONLY ) {
$rule = do_proto $proto, $ports, $sports . do_ratelimit( $ratelimit ) . do_user $user;
$loglevel = '';
}
} elsif ( $actiontype & NONAT ) {
#
# NONAT or ACCEPT+ -- May not specify a destination interface
#
fatal_error "Invalid DEST ($dest) in $action rule \"$line\"" if $dest =~ /:/;
expand_rule
ensure_chain ('nat' , $zones{$sourcezone}{type} eq 'firewall' ? 'OUTPUT' : dnat_chain $sourcezone) ,
$rule ,
$source ,
$dest ,
'' ,
'-j RETURN ' ,
$loglevel ,
$action ,
'';
}
#
# Add filter table rule, unless this is a NATONLY rule type
#
unless ( $actiontype & NATONLY ) {
if ( $actiontype & ACTION ) {
$action = (find_logactionchain $target)->{name};
$loglevel = '';
}
expand_rule
ensure_chain ('filter', $chain ) ,
$rule ,
$source ,
$dest ,
$origdest ,
"-j $action " ,
$loglevel ,
$action ,
'';
}
}
#
# Process a Record in the rules file
#
sub process_rule ( $$$$$$$$$ ) {
my ( $target, $source, $dest, $proto, $ports, $sports, $origdest, $ratelimit, $user ) = @_;
my $intrazone = 0;
my $includesrcfw = 1;
my $includedstfw = 1;
my $optimize = $config{OPTIMIZE};
my $thisline = $line;
#
# Section Names are optional so once we get to an actual rule, we need to be sure that
# we close off any missing sections.
#
unless ( $sectioned ) {
finish_section 'ESTABLISHED,RELATED';
$section = 'NEW';
$sectioned = 1;
}
#
# Handle Wildcards
#
if ( $source =~ /^all[-+]/ ) {
if ( $source eq 'all+' ) {
$source = 'all';
$intrazone = 1;
} elsif ( ( $source eq 'all+-' ) || ( $source eq 'all-+' ) ) {
$source = 'all';
$intrazone = 1;
$includesrcfw = 0;
} elsif ( $source eq 'all-' ) {
$source = 'all';
$includesrcfw = 0;
}
}
if ( $dest =~ /^all[-+]/ ) {
if ( $dest eq 'all+' ) {
$dest = 'all';
$intrazone = 1;
} elsif ( ( $dest eq 'all+-' ) || ( $dest eq 'all-+' ) ) {
$dest = 'all';
$intrazone = 1;
$includedstfw = 0;
} elsif ( $source eq 'all-' ) {
$dest = 'all';
$includedstfw = 0;
}
}
my $action = isolate_basic_target $target;
$optimize = 0 if $action =~ /!^/;
if ( $source eq 'all' ) {
for my $zone ( @zones ) {
if ( $includesrcfw || ( $zones{$zone}{type} ne 'firewall' ) ) {
if ( $dest eq 'all' ) {
for my $zone1 ( @zones ) {
if ( $includedstfw || ( $zones{$zone1}{type} ne 'firewall' ) ) {
if ( $intrazone || ( $zone ne $zone1 ) ) {
my $policychainref = $filter_table->{"${zone}2${zone1}"}{policychain};
fatal_error "No policy from zone $zone to zone $zone1" unless $policychainref;
if ( ( ( my $policy ) = $policychainref->{policy} ) ne 'NONE' ) {
if ( $optimize > 0 ) {
my $loglevel = $policychainref->{loglevel};
if ( $loglevel ) {
next if $target eq "${policy}:$loglevel}";
} else {
next if $action eq $policy;
}
}
process_rule1 $target, $zone, $zone1 , $proto, $ports, $sports, $origdest, $ratelimit, $user;
}
}
}
}
} else {
process_rule1 $target, $zone, $dest , $proto, $ports, $sports, $origdest, $ratelimit, $user;
}
}
}
} elsif ( $dest eq 'all' ) {
for my $zone1 ( @zones ) {
my $zone = ( split /:/, $source )[0];
if ( ( $includedstfw || ( $zones{$zone1}{type} ne 'firewall') ) &&( ( $zone ne $zone1 ) || $intrazone) ) {
process_rule1 $target, $source, $zone1 , $proto, $ports, $sports, $origdest, $ratelimit, $user;
}
}
} else {
process_rule1 $target, $source, $dest, $proto, $ports, $sports, $origdest, $ratelimit, $user;
}
progress_message " Rule \"$thisline\" $done";
}
#
# Process the Rules File
#
sub process_rules() {
open RULES, "$ENV{TMP_DIR}/rules" or fatal_error "Unable to open stripped rules file: $!";
while ( $line = <RULES> ) {
chomp $line;
$line =~ s/\s+/ /g;
my ( $target, $source, $dest, $proto, $ports, $sports, $origdest, $ratelimit, $user, $extra ) = split /\s+/, $line;
if ( $target eq 'COMMENT' ) {
if ( $capabilities{COMMENTS} ) {
( $comment = $line ) =~ s/^\s*COMMENT\s*//;
$comment =~ s/\s*$//;
} else {
warning_message "COMMENT ignored -- requires comment support in iptables/Netfilter";
}
} elsif ( $target eq 'SECTION' ) {
fatal_error "Invalid SECTION $source" unless defined $sections{$source};
fatal_error "Duplicate or out of order SECTION $source" if $sections{$source};
fatal_error "Invalid Section $source $dest" if $dest;
$sectioned = 1;
$sections{$source} = 1;
if ( $section eq 'RELATED' ) {
$sections{ESTABLISHED} = 1;
finish_section 'ESTABLISHED';
} elsif ( $section eq 'NEW' ) {
@sections{'ESTABLISHED','RELATED'} = ( 1, 1 );
finish_section ( ( $section eq 'RELATED' ) ? 'RELATED' : 'ESTABLISHED,RELATED' );
}
$section = $source;
} else {
fatal_error "Invalid rules file entry: \"$line\"" if $extra;
process_rule $target, $source, $dest, $proto, $ports, $sports, $origdest, $ratelimit, $user;
}
}
close RULES;
$comment = '';
$section = 'DONE';
}
#
# To quote an old comment, generate_matrix makes a sows ear out of a silk purse.
#