Add new configuration options and optimization changes from 4.5

Signed-off-by: Tom Eastep <teastep@shorewall.net>
This commit is contained in:
Tom Eastep 2010-01-16 09:53:53 -08:00
parent c39f3c12c9
commit 4bf0b8e1dd
7 changed files with 716 additions and 164 deletions

View File

@ -3,7 +3,7 @@
#
# This program is under GPL [http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt]
#
# (c) 2007,2008 - Tom Eastep (teastep@shorewall.net)
# (c) 2007,2008,2009,2010 - Tom Eastep (teastep@shorewall.net)
#
# Complete documentation is available at http://shorewall.net
#
@ -35,7 +35,7 @@ use strict;
our @ISA = qw(Exporter);
our @EXPORT = qw( setup_accounting );
our @EXPORT_OK = qw( );
our $VERSION = '4.4_6';
our $VERSION = '4.4.7';
#
# Called by the compiler to [re-]initialize this module's state
@ -185,17 +185,17 @@ sub setup_accounting() {
if ( have_bridges ) {
if ( $filter_table->{accounting} ) {
for my $chain ( qw/INPUT FORWARD/ ) {
insert_rule1 $filter_table->{$chain}, 0, '-j accounting';
add_jump( $filter_table->{$chain}, 'accounting', 0, '', 0, 0 );
}
}
if ( $filter_table->{accountout} ) {
insert_rule1 $filter_table->{OUTPUT}, 0, '-j accountout';
add_jump( $filter_table->{OUTPUT}, 'accountout', 0, '', 0, 0 );
}
} else {
if ( $filter_table->{accounting} ) {
for my $chain ( qw/INPUT FORWARD OUTPUT/ ) {
insert_rule1 $filter_table->{$chain}, 0, '-j accounting';
add_jump( $filter_table->{$chain}, 'accounting', 0, '', 0, 0 );
}
}
}

View File

@ -57,7 +57,7 @@ our @EXPORT = qw( merge_levels
$macro_commands
);
our @EXPORT_OK = qw( initialize );
our $VERSION = '4.4_6';
our $VERSION = '4.4_7';
#
# Used Actions. Each action that is actually used has an entry with value 1.
@ -305,10 +305,10 @@ sub map_old_actions( $ ) {
# Create and record a log action chain -- Log action chains have names
# that are formed from the action name by prepending a "%" and appending
# a 1- or 2-digit sequence number. In the functions that follow,
# the CHAIN, LEVEL and TAG variable serves as arguments to the user's
# the $chain, $level and $tag variable serves as arguments to the user's
# exit. We call the exit corresponding to the name of the action but we
# set CHAIN to the name of the iptables chain where rules are to be added.
# Similarly, LEVEL and TAG contain the log level and log tag respectively.
# set $chain to the name of the iptables chain where rules are to be added.
# Similarly, $level and $tag contain the log level and log tag respectively.
#
# The maximum length of a chain name is 30 characters -- since the log
# action chain name is 2-3 characters longer than the base chain name,
@ -341,6 +341,8 @@ sub createlogactionchain( $$ ) {
unless ( $targets{$action} & BUILTIN ) {
dont_optimize $chainref;
my $file = find_file $chain;
if ( -f $file ) {
@ -367,6 +369,8 @@ sub createsimpleactionchain( $ ) {
unless ( $targets{$action} & BUILTIN ) {
dont_optimize $chainref;
my $file = find_file $action;
if ( -f $file ) {
@ -384,7 +388,7 @@ sub createsimpleactionchain( $ ) {
}
#
# Create an action chain and run it's associated user exit
# Create an action chain and run its associated user exit
#
sub createactionchain( $ ) {
my ( $action , $level ) = split_action $_[0];
@ -574,7 +578,7 @@ sub process_actions2 () {
for my $target (keys %usedactions) {
my ($action, $level) = split_action $target;
my $actionref = $actions{$action};
fatal_error "Null Action Reference in process_actions2" unless $actionref;
assert( $actionref );
for my $action1 ( keys %{$actionref->{requires}} ) {
my $action2 = merge_levels $target, $action1;
unless ( $usedactions{ $action2 } ) {
@ -834,15 +838,15 @@ sub allowBcast( $$$ ) {
sub dropNotSyn ( $$$ ) {
my ($chainref, $level, $tag) = @_;
log_rule_limit $level, $chainref, 'dropNotSyn' , 'DROP', '', $tag, 'add', '-p tcp ! --syn ' if $level ne '';
add_rule $chainref , '-p tcp ! --syn -j DROP';
log_rule_limit $level, $chainref, 'dropNotSyn' , 'DROP', '', $tag, 'add', '-p 6 ! --syn ' if $level ne '';
add_rule $chainref , '-p 6 ! --syn -j DROP';
}
sub rejNotSyn ( $$$ ) {
my ($chainref, $level, $tag) = @_;
log_rule_limit $level, $chainref, 'rejNotSyn' , 'REJECT', '', $tag, 'add', '-p tcp ! --syn ' if $level ne '';
add_rule $chainref , '-p tcp ! --syn -j REJECT --reject-with tcp-reset';
log_rule_limit $level, $chainref, 'rejNotSyn' , 'REJECT', '', $tag, 'add', '-p 6 ! --syn ' if $level ne '';
add_rule $chainref , '-p 6 ! --syn -j REJECT --reject-with tcp-reset';
}
sub dropInvalid ( $$$ ) {
@ -860,18 +864,19 @@ sub allowInvalid ( $$$ ) {
}
sub forwardUPnP ( $$$ ) {
dont_optimize 'forwardUPnP';
}
sub allowinUPnP ( $$$ ) {
my ($chainref, $level, $tag) = @_;
if ( $level ne '' ) {
log_rule_limit $level, $chainref, 'allowinUPnP' , 'ACCEPT', '', $tag, 'add', '-p udp --dport 1900 ';
log_rule_limit $level, $chainref, 'allowinUPnP' , 'ACCEPT', '', $tag, 'add', '-p tcp --dport 49152 ';
log_rule_limit $level, $chainref, 'allowinUPnP' , 'ACCEPT', '', $tag, 'add', '-p 17 --dport 1900 ';
log_rule_limit $level, $chainref, 'allowinUPnP' , 'ACCEPT', '', $tag, 'add', '-p 6 --dport 49152 ';
}
add_rule $chainref, '-p udp --dport 1900 -j ACCEPT';
add_rule $chainref, '-p tcp --dport 49152 -j ACCEPT';
add_rule $chainref, '-p 17 --dport 1900 -j ACCEPT';
add_rule $chainref, '-p 6 --dport 49152 -j ACCEPT';
}
sub Limit( $$$ ) {
@ -897,7 +902,7 @@ sub Limit( $$$ ) {
my $xchainref = new_chain 'filter' , "$chainref->{name}%";
log_rule_limit $level, $xchainref, $tag[0], 'DROP', '', '', 'add', '';
add_rule $xchainref, '-j DROP';
add_rule $chainref, "-m recent --name $set --update --seconds $tag[2] --hitcount $count -j $xchainref->{name}";
add_jump $chainref, $xchainref, 0, "-m recent --name $set --update --seconds $tag[2] --hitcount $count ";
} else {
add_rule $chainref, "-m recent --update --name $set --seconds $tag[2] --hitcount $count -j DROP";
}

View File

@ -3,7 +3,7 @@
#
# This program is under GPL [http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt]
#
# (c) 2007,2008,2009 - Tom Eastep (teastep@shorewall.net)
# (c) 2007,2008,2009,2010 - Tom Eastep (teastep@shorewall.net)
#
# Complete documentation is available at http://shorewall.net
#
@ -42,6 +42,9 @@ our @EXPORT = qw(
new_manual_chain
ensure_manual_chain
log_rule_limit
dont_optimize
dont_delete
dont_move
%chain_table
$raw_table
@ -113,6 +116,8 @@ our %EXPORT_TAGS = (
new_nat_chain
ensure_filter_chain
finish_section
optimize_chain
optimize_ruleset
setup_zone_mss
newexclusionchain
newnonatchain
@ -168,7 +173,7 @@ our %EXPORT_TAGS = (
Exporter::export_ok_tags('internal');
our $VERSION = '4.4_6';
our $VERSION = '4.4_7';
#
# Chain Table
@ -181,6 +186,9 @@ our $VERSION = '4.4_6';
# builtin => undef|1 -- If 1, one of Netfilter's built-in chains.
# manual => undef|1 -- If 1, a manual chain.
# accounting => undef|1 -- If 1, an accounting chain
# dont_optimize=> undef|1 -- Don't optimize away if this chain is 'short'
# dont_delete => undef|1 -- Don't delete if this chain is not referenced
# dont_move => undef|1 -- Don't copy the rules of this chain somewhere else
# log => <logging rule number for use when LOGRULENUMBERS>
# policy => <policy>
# policychain => <name of policy chain> -- self-reference if this is a policy chain
@ -195,6 +203,8 @@ our $VERSION = '4.4_6';
# <rule2>
# ...
# ]
# logchains => { <key1> = <chainref1>, ... }
# references => { <ref1> => <refs>, <ref2> => <refs>, ... }
# } ,
# <chain2> => ...
# }
@ -362,7 +372,9 @@ sub initialize( $ ) {
$idiotcount = 0;
$idiotcount1 = 0;
$warningcount = 0;
#
# The chain table is initialized via a call to initialize_chain_table() after the configuration and capabilities have been determined.
#
}
#
@ -541,40 +553,14 @@ sub add_rule($$;$)
}
#
# Add a jump from the chain represented by the reference in the first argument to
# the target in the second argument. The third argument determines if a GOTO may be
# used rather than a jump. The optional fourth argument specifies any matches to be
# included in the rule and must end with a space character if it is non-null. The
# optional 5th argument causes long port lists to be split.
# Make the first chain a referent of the second
#
sub add_reference ( $$ ) {
my ( $fromref, $to ) = @_;
sub add_jump( $$$;$$ ) {
my ( $fromref, $to, $goto_ok, $predicate, $expandports ) = @_;
my $toref = reftype $to ? $to : $chain_table{$fromref->{table}}{$to};
$predicate |= '';
my $toref;
#
# The second argument may be a scalar (chain name or builtin target) or a chain reference
#
if ( reftype $to ) {
$toref = $to;
$to = $toref->{name};
} else {
#
# Ensure that we have the chain unless it is a builtin like 'ACCEPT'
#
$toref = ensure_chain( $fromref->{table} , $to ) unless $builtin_target{ $to };
}
#
# If the destination is a chain, mark it referenced
#
$toref->{referenced} = 1 if $toref;
my $param = $goto_ok && $toref && $capabilities{GOTO_TARGET} ? 'g' : 'j';
add_rule ($fromref, join( '', $predicate, "-$param $to" ), $expandports || 0 );
$toref->{references}{$fromref->{name}}++;
}
#
@ -586,7 +572,7 @@ sub purge_jump ( $$ ) {
my $to = $toref->{name};
for ( @{$fromref->{rules}} ) {
$_ = undef if / -[gj] ${to}\b/;
$_ = undef if defined && / -[gj] ${to}\b/;
}
$toref->{referenced} = 0 unless @{$toref->{rules}};
@ -621,6 +607,49 @@ sub insert_rule($$$) {
insert_rule1( $chainref, $number - 1, $rule );
}
#
# Add a jump from the chain represented by the reference in the first argument to
# the target in the second argument. The third argument determines if a GOTO may be
# used rather than a jump. The optional fourth argument specifies any matches to be
# included in the rule and must end with a space character if it is non-null. The
# optional 5th argument causes long port lists to be split. The optional 6th
# argument, if passed, gives the 0-relative index where the jump is to be inserted.
#
sub add_jump( $$$;$$$ ) {
my ( $fromref, $to, $goto_ok, $predicate, $expandports, $index ) = @_;
$predicate |= '';
my $toref;
#
# The second argument may be a scalar (chain name or builtin target) or a chain reference
#
if ( reftype $to ) {
$toref = $to;
$to = $toref->{name};
} else {
#
# Ensure that we have the chain unless it is a builtin like 'ACCEPT'
#
$toref = ensure_chain( $fromref->{table} , $to ) unless $builtin_target{ $to };
}
#
# If the destination is a chain, mark it referenced
#
$toref->{referenced} = 1, add_reference $fromref, $toref if $toref;
my $param = $goto_ok && $toref && $capabilities{GOTO_TARGET} ? 'g' : 'j';
if ( defined $index ) {
assert( ! $expandports );
insert_rule1( $fromref, $index, join( '', $predicate, "-$param $to" ));
} else {
add_rule ($fromref, join( '', $predicate, "-$param $to" ), $expandports || 0 );
}
}
#
# Insert a tunnel rule into the passed chain. Tunnel rules are inserted sequentially
# at the beginning of the 'NEW' section.
@ -643,6 +672,8 @@ sub move_rules( $$ ) {
if ( $chain1->{referenced} ) {
my $name = $chain1->{name};
my $rules = $chain2->{rules};
my $count = @{$chain1->{rules}};
#
# We allow '+' in chain names and '+' is an RE meta-character. Escape it.
#
@ -650,11 +681,52 @@ sub move_rules( $$ ) {
( s/\-([AI]) $name /-$1 $chain2->{name} / ) for @{$chain1->{rules}};
splice @{$chain2->{rules}}, 0, 0, @{$chain1->{rules}};
splice @{$rules}, 0, 0, @{$chain1->{rules}};
#
# In a firewall->x policy chain, multiple DHCP ACCEPT rules can be moved to the head of the chain.
# This hack avoids that.
#
shift @{$rules} if @{$rules} > 1 && $rules->[0] eq $rules->[1];
$chain2->{referenced} = 1;
$chain1->{referenced} = 0;
$chain1->{rules} = [];
$count;
}
}
#
# Replace the jump at the end of one chain (chain2) with the rules from another chain (chain1).
#
sub copy_rules( $$ ) {
my ($chain1, $chain2 ) = @_;
my $name1 = $chain1->{name};
my $name2 = $chain2->{name};
my @rules = @{$chain1->{rules}};
my $rules = $chain2->{rules};
my $count = @{$chain1->{rules}};
#
# We allow '+' in chain names and '+' is an RE meta-character. Escape it.
#
$name1 =~ s/\+/\\+/;
( s/\-([AI]) $name1(\b)/-$1 ${name2}$2/ ) for @rules;
pop @$rules; # Delete the jump to chain1
push @$rules, @rules;
#
# Add chain1's references to $chain2
#
$chain2->{references}{$_} += $chain1->{references}{$_} for keys %{$chain1->{references}};
progress_message " $count rules from $chain1->{name} appended to $chain2->{name}";
unless ( --$chain1->{references}{$name2} ) {
delete $chain1->{references}{$name2};
$chain1->{referenced} = 0, progress_message " Unreferenced chain $name1 deleted" unless keys %{$chain1->{references}};
}
}
@ -899,7 +971,8 @@ sub new_chain($$)
table => $table,
loglevel => '',
log => 1,
cmdlevel => 0 };
cmdlevel => 0,
references => {} };
}
#
@ -916,6 +989,45 @@ sub ensure_chain($$)
$ref ? $ref : new_chain $table, $chain;
}
#
# Set the dont_optimize flag for a chain
#
sub dont_optimize( $ ) {
my $chain = shift;
my $chainref = reftype $chain ? $chain : $filter_table->{$chain};
$chainref->{dont_optimize} = 1;
$chainref;
}
#
# Set the dont_optimize and dont_delete flags for a chain
#
sub dont_delete( $ ) {
my $chain = shift;
my $chainref = reftype $chain ? $chain : $filter_table->{$chain};
$chainref->{dont_optimize} = $chainref->{dont_delete} = 1;
$chainref;
}
#
# Set the dont_move flag for a chain
#
sub dont_move( $ ) {
my $chain = shift;
my $chainref = reftype $chain ? $chain : $filter_table->{$chain};
$chainref->{dont_move} = 1;
$chainref;
}
sub finish_chain_section( $$ );
#
@ -957,6 +1069,7 @@ sub ensure_accounting_chain( $ )
$chainref = new_chain 'filter' , $chain;
$chainref->{accounting} = 1;
$chainref->{referenced} = 1;
$chainref->{dont_optimize} = 1 unless $config{OPTIMIZE_ACCOUNTING};
if ( $chain ne 'accounting' ) {
my $file = find_file $chain;
@ -1013,6 +1126,8 @@ sub new_builtin_chain($$$)
$chainref->{referenced} = 1;
$chainref->{policy} = $policy;
$chainref->{builtin} = 1;
$chainref->{dont_delete} = 1;
$chainref->{dont_move} = 1;
$chainref;
}
@ -1188,6 +1303,335 @@ sub finish_section ( $ ) {
}
}
#
# Delete redundant ACCEPT rules from the end of a policy chain whose policy is ACCEPT
#
sub optimize_chain( $ ) {
my $chainref = shift;
if ( $chainref->{referenced} ) {
my $rules = $chainref->{rules};
my $count = 0;
pop @$rules;
pop @$rules, $count++ while @$rules && $rules->[-1] =~ /-j ACCEPT/;
if ( @${rules} ) {
add_rule $chainref, '-j ACCEPT';
progress_message " $count ACCEPT rules deleted from policy chain $chainref->{name}" if $count;
} else {
#
# The chain is now empty -- change all references to ACCEPT
#
$count = 0;
for my $fromref ( map $filter_table->{$_} , keys %{$chainref->{references}} ) {
defined && s/ -[jg] $chainref->{name}$/ -j ACCEPT/ && $count++ for @{$fromref->{rules}};
}
progress_message " $count references to ACCEPT policy chain $chainref->{name} replaced";
$chainref->{referenced} = 0;
}
}
}
#
# Delete the references to the passed chain
#
sub delete_references( $ ) {
my $chainref = shift;
my $table = $chainref->{table};
my $count = 0;
for my $fromref ( map $chain_table{$table}{$_} , keys %{$chainref->{references}} ) {
for ( @{$fromref->{rules}} ) {
$_ = undef, $count++ if defined && / -[jg] $chainref->{name}$/;
}
}
if ( $count ) {
progress_message " $count references to empty chain $chainref->{name} deleted";
} else {
progress_message " Empty chain $chainref->{name} deleted";
}
$chainref->{referenced} = 0;
$count;
}
#
# Replace jumps to the passed chain with jumps to the passed target
#
sub replace_references( $$ ) {
my ( $chainref, $target ) = @_;
my $table = $chainref->{table};
my $count = 0;
if ( defined $chain_table{$table}{$target} && ! $chain_table{$table}{$target}{builtin} ) {
#
# The target is a chain -- use the jump type from each referencing rule
#
for my $fromref ( map $chain_table{$table}{$_} , keys %{$chainref->{references}} ) {
if ( $fromref->{referenced} ) {
defined && s/ -([jg]) $chainref->{name}(\b)/ -$1 ${target}$2/ && $count++ for @{$fromref->{rules}};
}
}
} else {
#
# The target is a builtin -- we must use '-j'
#
for my $fromref ( map $chain_table{$table}{$_} , keys %{$chainref->{references}} ) {
if ( $fromref->{referenced} ) {
defined && s/ -[jg] $chainref->{name}(\b)/ -j ${target}$1/ && $count++ for @{$fromref->{rules}};
}
}
}
progress_message " $count references to 1-rule chain $chainref->{name} replaced" if $count;
$chainref->{referenced} = 0;
}
#
# Replace jumps to the passed chain with jumps to the passed target while
# adding the passed matches to the rule.
#
sub replace_references1( $$$ ) {
my ( $chainref, $target, $matches ) = @_;
my $table = $chainref->{table};
my $count = 0;
#
# Note: If $matches is non-empty, then it begins with white space
#
if ( defined $chain_table{$table}{$target} && ! $chain_table{$table}{$target}{builtin} ) {
#
# The target is a chain -- use the jump type from each referencing rule
#
for my $fromref ( map $chain_table{$table}{$_} , keys %{$chainref->{references}} ) {
if ( $fromref->{referenced} ) {
for ( @{$fromref->{rules}} ) {
if ( defined && /^-A $fromref->{name} .*-[jg] $chainref->{name}\b/ ) {
#
# Prevent multiple '-p' matches
#
s/ -p [^ ]+ / / if / -p / && $matches =~ / -p /;
s/\s+-([jg]) $chainref->{name}(\b)/$matches -$1 ${target}$2/;
$count++;
}
}
}
}
} else {
#
# The target is a builtin -- we must use '-j'
#
for my $fromref ( map $chain_table{$table}{$_} , keys %{$chainref->{references}} ) {
if ( $fromref->{referenced} ) {
for ( @{$fromref->{rules}} ) {
if ( defined && /^-A $fromref->{name} .*-[jg] $chainref->{name}\b/ ) {
#
# Prevent multiple '-p' matches
#
s/ -p [^ ]+ / / if / -p / && $matches =~ / -p /;
s/\s+-[jg] $chainref->{name}(\b)/$matches -j ${target}$1/;
$count++;
}
}
}
}
}
progress_message " $count references to 1-rule chain $chainref->{name} replaced" if $count;
$chainref->{referenced} = 0;
}
#
# The passed builtin chain has a single rule. If the target is a user chain without 'dont"move', move the rules from the
# chain to the builtin and return true; otherwise, do nothing and return false.
#
sub conditionally_move_rules( $$ ) {
my ( $chainref, $target ) = @_;
if ( $target =~ /^\s*([^\s]+)/ ) {
#
# The above test is simply to isolate the basic target in $1
#
my $basictarget = $1;
my $targetref = $chain_table{$chainref->{table}}{$basictarget};
if ( $targetref && ! $targetref->{dont_move} ) {
#
# Move is safe -- start with an empty rule list
#
$chainref->{rules} = [];
my $count = move_rules( $targetref, $chainref );
progress_message " $count rules moved from chain $targetref->{name} to chain $chainref->{name}" if $count;
1;
}
}
}
#
# Perform Optimization
#
sub optimize_ruleset() {
#
# Make repeated passes through each table looking for short chains (those with less than 2 entries)
#
# When an unreferenced chain is found, it is deleted unless its 'dont_delete' flag is set.
# When an empty chain is found, delete the references to it.
# When a chain with a single entry is found, replace it's references by its contents
#
# The search continues until no short chains remain
# Chains with 'dont_optimize = 1' are exempted from optimization
#
for my $table ( qw/ raw mangle nat filter/ ) {
next if $family == F_IPV6 && $table eq 'nat';
my $progress = 1;
my $passes = 0;
while ( $progress ) {
$progress = 0;
$passes++;
for my $chainref ( grep $_->{referenced}, values %{$chain_table{$table}} ) {
#
# If the chain isn't branched to, then delete it
#
unless ( $chainref->{dont_delete} || keys %{$chainref->{references}} ) {
$chainref->{referenced} = 0;
progress_message " Unreferenced chain $chainref->{name} deleted";
next;
}
unless ( $chainref->{dont_optimize} ) {
#
# Next count the rules -- we must do that because
# we delete rules by setting them
# to nil.
my $numrules = 0;
my $firstrule;
my $lastrule;
for ( @{$chainref->{rules}} ) {
if ( defined ) {
$numrules++;
$lastrule = $_;
$firstrule = $_ unless defined $firstrule;
}
}
if ( $numrules == 0 ) {
#
# No rules in this chain
#
if ( $chainref->{builtin} ) {
#
# Built-in -- mark it 'dont_optimize' so we ignore it in follow-on passes
#
$chainref->{dont_optimize} = 1;
} else {
#
# Not a built-in -- we can delete it and it's references
#
delete_references $chainref;
$progress = 1;
}
} elsif ( $numrules == 1 ) {
#
# Chain has a single non-nil rule which is in $firstrule
#
if ( $firstrule =~ /^-A $chainref->{name} -[jg] (.*)$/ ) {
#
# Easy case -- the rule is a simple jump
#
if ( $chainref->{builtin} ) {
#
# A built-in chain. If the target is a user chain without 'dont_move',
# we can move its rules to the built-in
#
if ( conditionally_move_rules $chainref, $1 ) {
#
# Target was a user chain -- rules moved
#
$progress = 1;
} else {
#
# Target was a built-in. Ignore this chain in follow-on passes
#
$chainref->{dont_optimize} = 1;
}
} else {
#
# Replace all references to this chain with references to the target
#
replace_references $chainref, $1;
$progress = 1;
}
} elsif ( $firstrule =~ /-A $chainref->{name}( .*) -[jg] (.*)$/ ) {
#
# Not so easy -- the rule contains matches
#
if ( $chainref->{builtin} ) {
#
# This case requires a new rule merging algorithm. Ignore this chain for
# now.
#
$chainref->{dont_optimize} = 1;
} else {
#
# Replace references to this chain with the target and add the predicates
#
replace_references1 $chainref, $2, $1;
$progress = 1;
}
}
}
}
}
}
#
# In this loop, we look for chains that end in an unconditional jump. If the target of the jump
# is subject to optimization (dont_optimize = false), the jump is replaced by target's rules.
#
$progress = 1;
while ( $progress ) {
$progress = 0;
$passes++;
for my $chainref ( grep $_->{referenced}, values %{$chain_table{$table}} ) {
my $lastrule;
for ( @{$chainref->{rules}} ) {
$lastrule = $_ if defined;
}
if ( defined $lastrule && $lastrule =~ /^-A $chainref->{name} -[jg] (.*)$/ ) {
#
# Last rule is a simple branch
my $targetref = $chain_table{$table}{$1};
if ( $targetref && ! ( $targetref->{builtin} || $targetref->{dont_move} ) ) {
copy_rules( $targetref, $chainref );
$progress = 1;
}
}
}
}
progress_message " Table $table Optimized -- Passes = $passes";
progress_message '';
}
}
#
# Helper for set_mss
#
@ -1242,6 +1686,39 @@ sub newlogchain() {
"log${seq}";
}
#
# If there is already a logging chain associated with the passed rules chain that matches these
# parameters, then return a reference to it.
#
# Otherwise, create such a chain and store a reference in chainref's 'logchains' hash. Return the
# reference.
#
sub logchain( $$$$$$ ) {
my ( $chainref, $loglevel, $logtag, $exceptionrule, $disposition, $target ) = @_;
my $key = join( ':', $loglevel, $logtag, $exceptionrule, $disposition, $target );
my $logchainref = $chainref->{logchains}{$key};
unless ( $logchainref ) {
$logchainref = $chainref->{logchains}{$key} = new_chain $chainref->{table}, newlogchain;
#
# Now add the log rule and target rule without matches to the log chain.
#
log_rule_limit(
$loglevel ,
$logchainref ,
$chainref->{name} ,
$disposition ,
'',
$logtag,
'add',
'' );
add_rule( $logchainref, $exceptionrule . $target );
}
$logchainref;
}
sub newnonatchain() {
my $seq = $chainseq++;
"nonat${seq}";
@ -1915,7 +2392,7 @@ sub match_ipsec_out( $$ ) {
# Generate a log message
#
sub log_rule_limit( $$$$$$$$ ) {
my ($level, $chainref, $chain, $disposition, $limit, $tag, $command, $predicates ) = @_;
my ($level, $chainref, $chain, $disposition, $limit, $tag, $command, $matches ) = @_;
my $prefix = '';
@ -1923,11 +2400,11 @@ sub log_rule_limit( $$$$$$$$ ) {
return 1 if $level eq '';
$predicates .= ' ' if $predicates && substr( $predicates, -1, 1 ) ne ' ';
$matches .= ' ' if $matches && substr( $matches, -1, 1 ) ne ' ';
unless ( $predicates =~ /-m limit / ) {
unless ( $matches =~ /-m limit / ) {
$limit = $globals{LOGLIMIT} unless $limit && $limit ne '-';
$predicates .= $limit if $limit;
$matches .= $limit if $limit;
}
if ( $config{LOGFORMAT} =~ /^\s*$/ ) {
@ -1976,28 +2453,28 @@ sub log_rule_limit( $$$$$$$$ ) {
}
if ( $command eq 'add' ) {
add_rule ( $chainref, $predicates . $prefix , 1 );
add_rule ( $chainref, $matches . $prefix , 1 );
} else {
insert_rule1 ( $chainref , 0 , $predicates . $prefix );
insert_rule1 ( $chainref , 0 , $matches . $prefix );
}
}
sub log_rule( $$$$ ) {
my ( $level, $chainref, $disposition, $predicates ) = @_;
my ( $level, $chainref, $disposition, $matches ) = @_;
log_rule_limit $level, $chainref, $chainref->{name} , $disposition, $globals{LOGLIMIT}, '', 'add', $predicates;
log_rule_limit $level, $chainref, $chainref->{name} , $disposition, $globals{LOGLIMIT}, '', 'add', $matches;
}
#
# If the destination chain exists, then at the end of the source chain add a jump to the destination.
#
sub addnatjump( $$$ ) {
my ( $source , $dest, $predicates ) = @_;
my ( $source , $dest, $matches ) = @_;
my $destref = $nat_table->{$dest} || {};
if ( $destref->{referenced} ) {
add_rule $nat_table->{$source} , $predicates . "-j $dest";
add_jump $nat_table->{$source} , $dest , 0, $matches;
} else {
clearrule;
}
@ -2371,7 +2848,7 @@ sub expand_rule( $$$$$$$$$$;$ )
$origdest, # ORIGINAL DEST
$target, # Target ('-j' part of the rule)
$loglevel , # Log level (and tag)
$disposition, # Primative part of the target (RETURN, ACCEPT, ...)
$disposition, # Primtive part of the target (RETURN, ACCEPT, ...)
$exceptionrule,# Caller's matches used in exclusion case
$logname, # Name of chain to name in log messages
) = @_;
@ -2424,9 +2901,12 @@ sub expand_rule( $$$$$$$$$$;$ )
#
# Mark Target as referenced, if it's a chain
#
if ( $disposition ) {
my $targetref = $chain_table{$chainref->{table}}{$disposition};
$targetref->{referenced} = 1 if $targetref;
if ( $target =~ /-[jg]\s+([^\s]+)\b/ ) {
my $targetref = $chain_table{$chainref->{table}}{$1};
if ( $targetref ) {
$targetref->{referenced} = 1;
add_reference $chainref, $targetref;
}
}
#
@ -2704,8 +3184,13 @@ sub expand_rule( $$$$$$$$$$;$ )
#
fatal_error "Exclusion is not possible in ACCEPT+/CONTINUE/NONAT rules" if $disposition eq 'RETURN';
#
# Create the Exclusion Chain
#
my $echain = newexclusionchain;
my $echainref = new_chain $chainref->{table}, $echain;
#
# Use the current rule and send all possible matches to the exclusion chain
#
@ -2716,16 +3201,11 @@ sub expand_rule( $$$$$$$$$$;$ )
#
# We evaluate the source net match in the inner loop to accomodate systems without $capabilities{KLUDGEFREE}
#
add_rule( $chainref, join( '', $rule, match_source_net( $inet, $restriction ), match_dest_net( $dnet ), $onet, "-j $echain" ), 1 );
add_jump( $chainref, $echainref, 0, join( '', $rule, match_source_net( $inet, $restriction ), match_dest_net( $dnet ), $onet ), 1 );
}
}
}
#
# Create the Exclusion Chain
#
my $echainref = new_chain $chainref->{table}, $echain;
#
# Generate RETURNs for each exclusion
#
@ -2754,33 +3234,20 @@ sub expand_rule( $$$$$$$$$$;$ )
for my $dnet ( mysplit $dnets ) {
$source_match = match_source_net( $inet, $restriction ) unless $capabilities{KLUDGEFREE};
my $dest_match = match_dest_net( $dnet );
my $predicates = join( '', $rule, $source_match, $dest_match, $onet );
my $matches = join( '', $rule, $source_match, $dest_match, $onet );
if ( $loglevel ne '' ) {
if ( $disposition ne 'LOG' ) {
unless ( $logname ) {
#
# Create a chain that both logs and applies the target action
# Find/Create a chain that both logs and applies the target action
# and jump to the log chain if all of the rule's conditions are met
#
my $logchainref = new_chain $chainref->{table}, newlogchain;
#
# Jump to the log chain if all of the rule's conditions are met
#
add_jump( $chainref, $logchainref, $builtin_target{$disposition}, $predicates, 1 );
#
# Now add the log rule and target rule without predicates to the log chain.
#
log_rule_limit(
$loglevel ,
$logchainref ,
$chain ,
$disposition ,
'',
$logtag,
'add',
'' );
add_rule( $logchainref, $exceptionrule . $target );
add_jump( $chainref,
logchain( $chainref, $loglevel, $logtag, $exceptionrule , $disposition, $target ),
$builtin_target{$disposition},
$matches,
1 );
} else {
log_rule_limit(
$loglevel ,
@ -2790,13 +3257,13 @@ sub expand_rule( $$$$$$$$$$;$ )
'',
$logtag,
'add',
$predicates );
$matches );
add_rule( $chainref, $predicates . $target, 1 );
add_rule( $chainref, $matches . $target, 1 );
}
} else {
#
# The log rule must be added with predicates to the rule chain
# The log rule must be added with matches to the rule chain
#
log_rule_limit(
$loglevel ,
@ -2806,14 +3273,14 @@ sub expand_rule( $$$$$$$$$$;$ )
'' ,
$logtag ,
'add' ,
$predicates
$matches
);
}
} else {
#
# No logging -- add the target rule with predicates to the rule chain
# No logging -- add the target rule with matches to the rule chain
#
add_rule( $chainref, $predicates . $target , 1 );
add_rule( $chainref, $matches . $target , 1 );
}
}
}

View File

@ -4,7 +4,7 @@
#
# This program is under GPL [http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt]
#
# (c) 2007,2008,2009 - Tom Eastep (teastep@shorewall.net)
# (c) 2007,2008,2009,2010 - Tom Eastep (teastep@shorewall.net)
#
# Complete documentation is available at http://shorewall.net
#
@ -43,7 +43,7 @@ use Shorewall::Raw;
our @ISA = qw(Exporter);
our @EXPORT = qw( compiler EXPORT TIMESTAMP DEBUG );
our @EXPORT_OK = qw( $export );
our $VERSION = '4.4_6';
our $VERSION = '4.4_7';
our $export;
@ -816,7 +816,7 @@ sub compiler {
#
# Accounting.
#
setup_accounting;
setup_accounting if $config{ACCOUNTING};
if ( $scriptfilename ) {
#
@ -824,6 +824,18 @@ sub compiler {
#
generate_matrix;
if ( $config{OPTIMIZE} & 6 ) {
progress_message2 'Optimizing Ruleset...';
#
# Optimize Policy Chains
#
optimize_policy_chains if $config{OPTIMIZE} & 2;
#
# More Optimization
#
optimize_ruleset if $config{OPTIMIZE} & 4;
}
enable_script;
#
# I N I T I A L I Z E
@ -845,7 +857,7 @@ sub compiler {
# S T O P _ F I R E W A L L
# (Writes the stop_firewall() function to the compiled script)
#
compile_stop_firewall( $test );
compile_stop_firewall( $test, $export );
#
# Copy the footer to the script
#
@ -868,10 +880,26 @@ sub compiler {
enable_script, generate_aux_config if $export;
} else {
#
# Checking the configuration only
# Just checking the configuration
#
if ( $preview ) {
#
# User wishes to preview the ruleset -- generate the rule matrix
#
generate_matrix;
if ( $config{OPTIMIZE} & 6 ) {
progress_message2 'Optimizing Ruleset...';
#
# Optimize Policy Chains
#
optimize_policy_chains if $config{OPTIMIZE} & 2;
#
# Ruleset Optimization
#
optimize_ruleset if $config{OPTIMIZE} & 4;
}
preview_netfilter_load;
}
#

View File

@ -128,7 +128,7 @@ our %EXPORT_TAGS = ( internal => [ qw( create_temp_script
Exporter::export_ok_tags('internal');
our $VERSION = '4.4_6';
our $VERSION = '4.4_7';
#
# describe the current command, it's present progressive, and it's completion.
@ -445,6 +445,9 @@ sub initialize( $ ) {
WIDE_TC_MARKS => undef,
TRACK_PROVIDERS => undef,
ZONE2ZONE => undef,
ACCOUNTING => undef,
OPTIMIZE_ACCOUNTING => undef,
DYNAMIC_BLACKLIST => undef,
#
# Packet Disposition
#
@ -561,6 +564,9 @@ sub initialize( $ ) {
WIDE_TC_MARKS => undef,
TRACK_PROVIDERS => undef,
ZONE2ZONE => undef,
ACCOUNTING => undef,
OPTIMIZE_ACCOUNTING => undef,
DYNAMIC_BLACKLIST => undef,
#
# Packet Disposition
#
@ -2517,6 +2523,9 @@ sub get_configuration( $ ) {
default_yes_no 'AUTOMAKE' , '';
default_yes_no 'WIDE_TC_MARKS' , '';
default_yes_no 'TRACK_PROVIDERS' , '';
default_yes_no 'ACCOUNTING' , 'Yes';
default_yes_no 'OPTIMIZE_ACCOUNTING' , '';
default_yes_no 'DYNAMIC_BLACKLIST' , 'Yes';
numeric_option 'TC_BITS', $config{WIDE_TC_MARKS} ? 14 : 8 , 0;
numeric_option 'MASK_BITS', $config{WIDE_TC_MARKS} ? 16 : 8, $config{TC_BITS};
@ -2638,7 +2647,7 @@ sub get_configuration( $ ) {
$val = numeric_value $config{OPTIMIZE};
fatal_error "Invalid OPTIMIZE value ($config{OPTIMIZE})" unless defined( $val ) && $val >= 0 && $val <= 1;
fatal_error "Invalid OPTIMIZE value ($config{OPTIMIZE})" unless defined( $val ) && $val >= 0 && $val <= 7;
$globals{MARKING_CHAIN} = $config{MARK_IN_FORWARD_CHAIN} ? 'tcfor' : 'tcpre';

View File

@ -3,7 +3,7 @@
#
# This program is under GPL [http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt]
#
# (c) 2007,2008,2009 - Tom Eastep (teastep@shorewall.net)
# (c) 2007,2008,2009,2010 - Tom Eastep (teastep@shorewall.net)
#
# Complete documentation is available at http://shorewall.net
#
@ -32,9 +32,9 @@ use Shorewall::Actions;
use strict;
our @ISA = qw(Exporter);
our @EXPORT = qw( validate_policy apply_policy_rules complete_standard_chain setup_syn_flood_chains save_policies );
our @EXPORT = qw( validate_policy apply_policy_rules complete_standard_chain setup_syn_flood_chains save_policies optimize_policy_chains);
our @EXPORT_OK = qw( );
our $VERSION = '4.4_4';
our $VERSION = '4.4_7';
# @policy_chains is a list of references to policy chains in the filter table
@ -362,7 +362,7 @@ sub policy_rules( $$$$$ ) {
unless ( $target eq 'NONE' ) {
add_rule $chainref, "-d 224.0.0.0/4 -j RETURN" if $dropmulticast && $target ne 'CONTINUE' && $target ne 'ACCEPT';
add_rule $chainref, "-j $default" if $default && $default ne 'none';
add_jump $chainref, $default, 0 if $default && $default ne 'none';
log_rule $loglevel , $chainref , $target , '' if $loglevel ne '';
fatal_error "Null target in policy_rules()" unless $target;
@ -418,11 +418,22 @@ sub apply_policy_rules() {
my $provisional = $chainref->{provisional};
my $default = $chainref->{default};
my $name = $chainref->{name};
my $synparms = $chainref->{synparms};
if ( $policy ne 'NONE' ) {
if ( ! $chainref->{referenced} && ( ! $provisional && $policy ne 'CONTINUE' ) ) {
unless ( $chainref->{referenced} || $provisional || $policy eq 'CONTINUE' ) {
if ( $config{OPTIMIZE} & 2 ) {
#
# This policy chain is empty and the only thing that we would put in it is
# the policy-related stuff. Don't create it if all we are going to put in it
# is a single jump. Generate_matrix() will just use the policy target when
# needed.
#
ensure_filter_chain $name, 1 if $default ne 'none' || $loglevel || $synparms || $config{MULTICAST} || ! ( $policy eq 'ACCEPT' || $config{FASTACCEPT} );
} else {
ensure_filter_chain $name, 1;
}
}
if ( $name =~ /^all[-2]|[-2]all$/ ) {
run_user_exit $chainref;
@ -487,4 +498,24 @@ sub setup_syn_flood_chains() {
}
}
#
# Optimize Policy chains with ACCEPT policy
#
sub optimize_policy_chains() {
for my $chainref ( grep $_->{policy} eq 'ACCEPT', @policy_chains ) {
optimize_chain ( $chainref );
}
#
# Often, fw->all has an ACCEPT policy. This code allows optimization in that case
#
my $outputrules = $filter_table->{OUTPUT}{rules};
if ( @{$outputrules} && $outputrules->[-1] =~ /-j ACCEPT/ ) {
optimize_chain( $filter_table->{OUTPUT} );
}
progress_message ' Policy chains optimized';
progress_message '';
}
1;

View File

@ -46,7 +46,7 @@ our @EXPORT = qw( process_tos
compile_stop_firewall
);
our @EXPORT_OK = qw( process_rule process_rule1 initialize );
our $VERSION = '4.4_6';
our $VERSION = '4.4_7';
#
# Set to one if we find a SECTION
@ -157,8 +157,8 @@ sub process_tos() {
}
unless ( $first_entry ) {
add_rule $mangle_table->{$stdchain}, "-j $chain" if $pretosref->{referenced};
add_rule $mangle_table->{OUTPUT}, "-j outtos" if $outtosref->{referenced};
add_jump( $mangle_table->{$stdchain}, $chain, 0 ) if $pretosref->{referenced};
add_jump( $mangle_table->{OUTPUT}, 'outtos', 0 ) if $outtosref->{referenced};
}
}
}
@ -214,7 +214,7 @@ sub add_rule_pair( $$$$ ) {
my ($chainref , $predicate , $target , $level ) = @_;
log_rule( $level, $chainref, "\U$target", $predicate ) if defined $level && $level ne '';
add_rule $chainref , "${predicate}-j $target";
add_jump( $chainref , $target, 0, $predicate );
}
sub setup_blacklist() {
@ -232,7 +232,7 @@ sub setup_blacklist() {
log_rule_limit( $level , $logchainref , 'blacklst' , $disposition , "$globals{LOGLIMIT}" , '', 'add', '' );
add_rule $logchainref, "-j $target" ;
add_jump $logchainref, $target, 1;
$target = 'blacklog';
}
@ -419,17 +419,21 @@ sub setup_mss();
sub add_common_rules() {
my $interface;
my $chainref;
my $level;
my $target;
my $rule;
my $list;
my $chain;
new_standard_chain 'dynamic';
my $state = $config{BLACKLISTNEWONLY} ? $globals{UNTRACKED} ? '-m state --state NEW,INVALID,UNTRACKED ' : '-m state --state NEW,INVALID ' : '';
my $level = $config{BLACKLIST_LOGLEVEL};
my $rejectref = dont_move new_standard_chain 'reject';
add_rule $filter_table->{$_}, "$state -j dynamic" for qw( INPUT FORWARD );
if ( $config{DYNAMIC_BLACKLIST} ) {
add_rule_pair dont_delete( new_standard_chain( 'logdrop' ) ), ' ' , 'DROP' , $level ;
add_rule_pair dont_delete( new_standard_chain( 'logreject' ) ), ' ' , 'reject' , $level ;
$chainref = dont_optimize( new_standard_chain( 'dynamic' ) );
add_jump $filter_table->{$_}, $chainref, 0, $state for qw( INPUT FORWARD );
}
setup_mss;
@ -437,13 +441,6 @@ sub add_common_rules() {
add_rule( $filter_table->{$_} , "-m state --state ESTABLISHED,RELATED -j ACCEPT" ) for qw( INPUT FORWARD OUTPUT );
}
my $rejectref = new_standard_chain 'reject';
$level = $config{BLACKLIST_LOGLEVEL};
add_rule_pair new_standard_chain( 'logdrop' ), ' ' , 'DROP' , $level ;
add_rule_pair new_standard_chain( 'logreject' ), ' ' , 'reject' , $level ;
for $interface ( all_interfaces ) {
ensure_chain( 'filter', $_ ) for first_chains( $interface ), output_chain( $interface );
}
@ -591,11 +588,11 @@ sub add_common_rules() {
$disposition = $config{TCP_FLAGS_DISPOSITION};
}
add_rule $chainref , "-p tcp --tcp-flags ALL FIN,URG,PSH -j $disposition";
add_rule $chainref , "-p tcp --tcp-flags ALL NONE -j $disposition";
add_rule $chainref , "-p tcp --tcp-flags SYN,RST SYN,RST -j $disposition";
add_rule $chainref , "-p tcp --tcp-flags SYN,FIN SYN,FIN -j $disposition";
add_rule $chainref , "-p tcp --syn --sport 0 -j $disposition";
add_jump $chainref , $disposition, 1, '-p tcp --tcp-flags ALL FIN,URG,PSH ';
add_jump $chainref , $disposition, 1, '-p tcp --tcp-flags ALL NONE ';
add_jump $chainref , $disposition, 1, '-p tcp --tcp-flags SYN,RST SYN,RST ';
add_jump $chainref , $disposition, 1, '-p tcp --tcp-flags SYN,FIN SYN,FIN ';
add_jump $chainref , $disposition, 1, '-p tcp --syn --sport 0 ';
for my $hostref ( @$list ) {
my $interface = $hostref->[0];
@ -618,12 +615,12 @@ sub add_common_rules() {
if ( @$list ) {
progress_message2 "$doing UPnP";
new_nat_chain( 'UPnP' );
dont_optimize new_nat_chain( 'UPnP' );
$announced = 1;
for $interface ( @$list ) {
add_rule $nat_table->{PREROUTING} , match_source_dev ( $interface ) . '-j UPnP';
add_jump $nat_table->{PREROUTING} , 'UPnP', 0, match_source_dev ( $interface );
}
}
@ -706,7 +703,7 @@ sub setup_mac_lists( $ ) {
my $chain = $chainref->{name};
add_rule $chainref, "-m recent --rcheck --seconds $ttl --name $chain -j RETURN";
add_rule $chainref, "-j $chain1ref->{name}";
add_jump $chainref, $chain1ref, 0;
add_rule $chainref, "-m recent --update --name $chain -j RETURN";
add_rule $chainref, "-m recent --set --name $chain";
}
@ -834,7 +831,7 @@ sub setup_mac_lists( $ ) {
run_user_exit2( 'maclog', $chainref );
log_rule_limit $level, $chainref , $chain , $disposition, '', '', 'add', '' if $level ne '';
add_rule $chainref, "-j $target";
add_jump $chainref, $target, 0;
}
}
}
@ -958,7 +955,7 @@ sub process_rule1 ( $$$$$$$$$$$$$ ) {
my ( $basictarget, $param ) = get_target_param $action;
my $rule = '';
my $actionchainref;
my $optimize = $wildcard ? ( $basictarget =~ /!$/ ? 0 : $config{OPTIMIZE} ) : 0;
my $optimize = $wildcard ? ( $basictarget =~ /!$/ ? 0 : $config{OPTIMIZE} & 1 ) : 0;
$param = '' unless defined $param;
@ -1154,12 +1151,22 @@ sub process_rule1 ( $$$$$$$$$$$$$ ) {
# Mark the chain as referenced and add appropriate rules from earlier sections.
#
$chainref = ensure_filter_chain $chain, 1;
#
# Don't let the rules in this chain be moved elsewhere
#
dont_move $chainref;
}
#
# Generate Fixed part of the rule
#
$rule = join( '', do_proto($proto, $ports, $sports), do_ratelimit( $ratelimit, $basictarget ) , do_user( $user ) , do_test( $mark , $globals{TC_MASK} ) , do_connlimit( $connlimit ), do_time( $time ) );
$rule = join( '',
do_proto($proto, $ports, $sports),
do_ratelimit( $ratelimit, $basictarget ) ,
do_user( $user ) ,
do_test( $mark , $globals{TC_MASK} ) ,
do_connlimit( $connlimit ),
do_time( $time ) );
unless ( $section eq 'NEW' ) {
fatal_error "Entries in the $section SECTION of the rules file not permitted with FASTACCEPT=Yes" if $config{FASTACCEPT};
@ -1292,7 +1299,11 @@ sub process_rule1 ( $$$$$$$$$$$$$ ) {
# - the target will be ACCEPT.
#
unless ( $actiontype & NATONLY ) {
$rule = join( '', do_proto( $proto, $ports, $sports ), do_ratelimit( $ratelimit, 'ACCEPT' ), do_user $user , do_test( $mark , $globals{TC_MASK} ) );
$rule = join( '',
do_proto( $proto, $ports, $sports ),
do_ratelimit( $ratelimit, 'ACCEPT' ),
do_user $user ,
do_test( $mark , $globals{TC_MASK} ) );
$loglevel = '';
$dest = $server;
$action = 'ACCEPT';
@ -1370,7 +1381,7 @@ sub process_rule1 ( $$$$$$$$$$$$$ ) {
"-j $tgt",
$loglevel ,
$log_action ,
''
'' ,
);
#
# Possible optimization if the rule just generated was a simple jump to the nonat chain
@ -1624,7 +1635,7 @@ sub add_interface_jumps {
my $fw = firewall_zone;
my $chainref = $filter_table->{rules_chain( ${fw}, ${fw} )};
add_rule $filter_table->{OUTPUT} , "-o lo -j " . ($chainref->{referenced} ? "$chainref->{name}" : 'ACCEPT' );
add_jump $filter_table->{OUTPUT} , ($chainref->{referenced} ? $chainref : 'ACCEPT' ), 0, '-o lo ';
add_rule $filter_table->{INPUT} , '-i lo -j ACCEPT';
}
@ -1657,7 +1668,8 @@ sub generate_matrix() {
if ( $chainref->{policy} ne 'CONTINUE' ) {
my $policyref = $filter_table->{$chainref->{policychain}};
assert( $policyref );
return $policyref->{name};
return $policyref->{name} if $policyref ne $chainref;
return $chainref->{policy} eq 'REJECT' ? 'reject' : $chainref->{policy};
}
''; # CONTINUE policy
@ -1739,7 +1751,7 @@ sub generate_matrix() {
#
# NOTRACK from firewall
#
add_rule $raw_table->{OUTPUT}, "-j $notrackref->{name}" if $notrackref->{referenced};
add_jump $raw_table->{OUTPUT}, $notrackref, 0 if $notrackref->{referenced};
#
# Main source-zone matrix-generation loop
#
@ -1906,7 +1918,7 @@ sub generate_matrix() {
my @dest_zones;
my $last_chain = '';
if ( $config{OPTIMIZE} > 0 ) {
if ( $config{OPTIMIZE} & 1 ) {
my @temp_zones;
for my $zone1 ( @zones ) {
@ -2007,7 +2019,7 @@ sub generate_matrix() {
my $match_source_dev = '';
my $forwardchainref = $filter_table->{forward_chain $interface};
if ( use_forward_chain( $interface ) || ( @{$forwardchainref->{rules} } && ! $chainref ) ) {
if ( use_forward_chain $interface || ( @{$forwardchainref->{rules} } && ! $chainref ) ) {
#
# Either we must use the interface's forwarding chain or that chain has rules and we have nowhere to move them
#
@ -2122,7 +2134,7 @@ sub setup_mss( ) {
#
# Send all forwarded SYN packets to the 'settcpmss' chain
#
add_rule $filter_table->{FORWARD} , "-p tcp --tcp-flags SYN,RST SYN -j settcpmss";
add_jump $filter_table->{FORWARD} , $chainref, 0, '-p tcp --tcp-flags SYN,RST SYN ';
my $in_match = '';
my $out_match = '';
@ -2150,8 +2162,8 @@ sub setup_mss( ) {
#
# Compile the stop_firewall() function
#
sub compile_stop_firewall( $ ) {
my $test = shift;
sub compile_stop_firewall( $$ ) {
my ( $test, $export ) = @_;
my $input = $filter_table->{INPUT};
my $output = $filter_table->{OUTPUT};