mirror of
https://gitlab.com/shorewall/code.git
synced 2025-06-20 01:37:59 +02: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;
|
$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
|
# 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
|
# chain table entry is returned. It is the caller's responsibility to
|
||||||
# to handle reference counting. If the target is a builtin, '' is
|
# ensure that the rules being merged are compatible.
|
||||||
# returned.
|
#
|
||||||
|
# It is also the caller's responsibility to handle reference counting.
|
||||||
|
# If the target is a builtin, '' is returned.
|
||||||
#
|
#
|
||||||
sub merge_rules( $$$ ) {
|
sub merge_rules( $$$ ) {
|
||||||
my ( $tableref, $toref, $fromref ) = @_;
|
my ( $tableref, $toref, $fromref ) = @_;
|
||||||
|
|
||||||
my $target = $fromref->{target};
|
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 ) {
|
for my $option ( @unique_options ) {
|
||||||
$toref->{$option} = $fromref->{$option} if exists $fromref->{$option};
|
$toref->{$option} = $fromref->{$option} if exists $fromref->{$option};
|
||||||
}
|
}
|
||||||
@ -2452,33 +2471,45 @@ sub replace_references1( $$ ) {
|
|||||||
my $count = 0;
|
my $count = 0;
|
||||||
my $name = $chainref->{name};
|
my $name = $chainref->{name};
|
||||||
my $target = $ruleref->{target};
|
my $target = $ruleref->{target};
|
||||||
|
my $delete = 1;
|
||||||
|
|
||||||
for my $fromref ( map $tableref->{$_} , keys %{$chainref->{references}} ) {
|
for my $fromref ( map $tableref->{$_} , keys %{$chainref->{references}} ) {
|
||||||
my $rule = 0;
|
my $rule = 0;
|
||||||
|
my $skipped = 0;
|
||||||
if ( $fromref->{referenced} ) {
|
if ( $fromref->{referenced} ) {
|
||||||
for ( @{$fromref->{rules}} ) {
|
for ( @{$fromref->{rules}} ) {
|
||||||
$rule++;
|
$rule++;
|
||||||
if ( $_->{target} eq $name ) {
|
if ( $_->{target} eq $name ) {
|
||||||
#
|
if ( compatible( $_ , $ruleref ) ) {
|
||||||
# The target is the passed chain -- merge the two rules into one
|
#
|
||||||
#
|
# The target is the passed chain -- merge the two rules into one
|
||||||
if ( my $targetref = merge_rules( $tableref, $_, $ruleref ) ) {
|
#
|
||||||
add_reference( $fromref, $targetref );
|
if ( my $targetref = merge_rules( $tableref, $_, $ruleref ) ) {
|
||||||
delete_reference( $fromref, $chainref );
|
add_reference( $fromref, $targetref );
|
||||||
}
|
delete_reference( $fromref, $chainref );
|
||||||
|
}
|
||||||
|
|
||||||
$count++;
|
$count++;
|
||||||
trace( $fromref, 'R', $rule, $_ ) if $debug;
|
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;
|
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 references to this chain with the target and add the matches
|
||||||
#
|
#
|
||||||
replace_references1 $chainref, $firstrule;
|
$progress = 1 if replace_references1 $chainref, $firstrule;
|
||||||
$progress = 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user