mirror of
https://gitlab.com/shorewall/code.git
synced 2024-11-08 16:54:10 +01:00
Don't combine incompatible chains
Signed-off-by: Tom Eastep <teastep@shorewall.net>
This commit is contained in:
parent
f31f3dc92a
commit
d3d9380df5
@ -809,21 +809,40 @@ sub format_rule( $$;$ ) {
|
||||
$rule;
|
||||
}
|
||||
|
||||
#
|
||||
# Check two rules to determine if the second rule can be merged into the first.
|
||||
#
|
||||
sub compatible( $$ ) {
|
||||
my ( $ref1, $ref2 ) = @_;
|
||||
my ( $val1, $val2 );
|
||||
|
||||
for ( @unique_options ) {
|
||||
if ( defined( $val1 = $ref1->{$_} ) && defined( $val2 = $ref2->{$_} ) ) {
|
||||
unless ( $val1 eq $val2 ) {
|
||||
my @val1 = split ' ', $val1;
|
||||
my @val2 = split ' ', $val2;
|
||||
|
||||
return 0 if @val1 > @val2 || $val1[0] ne $val2[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#
|
||||
# Merge two rules - If the target of the merged rule is a chain, a reference to its
|
||||
# chain table entry is returned. It is the caller's responsibility
|
||||
# to handle reference counting. If the target is a builtin, '' is
|
||||
# returned.
|
||||
# chain table entry is returned. It is the caller's responsibility to
|
||||
# ensure that the rules being merged are compatible.
|
||||
#
|
||||
# It is also the caller's responsibility to handle reference counting.
|
||||
# If the target is a builtin, '' is returned.
|
||||
#
|
||||
sub merge_rules( $$$ ) {
|
||||
my ( $tableref, $toref, $fromref ) = @_;
|
||||
|
||||
my $target = $fromref->{target};
|
||||
#
|
||||
# Since the 'to' rule is a jump to a chain containing the 'from' rule, we
|
||||
# assume that common unique option values are compatible (such as 'tcp' and
|
||||
# 'tcp ! syn').
|
||||
#
|
||||
|
||||
for my $option ( @unique_options ) {
|
||||
$toref->{$option} = $fromref->{$option} if exists $fromref->{$option};
|
||||
}
|
||||
@ -2452,33 +2471,45 @@ sub replace_references1( $$ ) {
|
||||
my $count = 0;
|
||||
my $name = $chainref->{name};
|
||||
my $target = $ruleref->{target};
|
||||
my $delete = 1;
|
||||
|
||||
for my $fromref ( map $tableref->{$_} , keys %{$chainref->{references}} ) {
|
||||
my $rule = 0;
|
||||
my $rule = 0;
|
||||
my $skipped = 0;
|
||||
if ( $fromref->{referenced} ) {
|
||||
for ( @{$fromref->{rules}} ) {
|
||||
$rule++;
|
||||
if ( $_->{target} eq $name ) {
|
||||
#
|
||||
# The target is the passed chain -- merge the two rules into one
|
||||
#
|
||||
if ( my $targetref = merge_rules( $tableref, $_, $ruleref ) ) {
|
||||
add_reference( $fromref, $targetref );
|
||||
delete_reference( $fromref, $chainref );
|
||||
}
|
||||
if ( $_->{target} eq $name ) {
|
||||
if ( compatible( $_ , $ruleref ) ) {
|
||||
#
|
||||
# The target is the passed chain -- merge the two rules into one
|
||||
#
|
||||
if ( my $targetref = merge_rules( $tableref, $_, $ruleref ) ) {
|
||||
add_reference( $fromref, $targetref );
|
||||
delete_reference( $fromref, $chainref );
|
||||
}
|
||||
|
||||
$count++;
|
||||
trace( $fromref, 'R', $rule, $_ ) if $debug;
|
||||
$count++;
|
||||
trace( $fromref, 'R', $rule, $_ ) if $debug;
|
||||
} else {
|
||||
$skipped++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete $tableref->{$target}{references}{$chainref->{name}} if $tableref->{$target};
|
||||
if ( $skipped ) {
|
||||
$delete = 0;
|
||||
} else {
|
||||
delete $tableref->{$target}{references}{$chainref->{name}} if $tableref->{$target};
|
||||
}
|
||||
}
|
||||
|
||||
progress_message " $count references to chain $chainref->{name} replaced" if $count;
|
||||
|
||||
delete_chain $chainref;
|
||||
delete_chain $chainref if $delete;
|
||||
|
||||
$count;
|
||||
}
|
||||
|
||||
#
|
||||
@ -2617,8 +2648,8 @@ sub optimize_level4( $$ ) {
|
||||
#
|
||||
# Replace references to this chain with the target and add the matches
|
||||
#
|
||||
replace_references1 $chainref, $firstrule;
|
||||
$progress = 1;
|
||||
$progress = 1 if replace_references1 $chainref, $firstrule;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user