diff --git a/Shorewall/Perl/Shorewall/Chains.pm b/Shorewall/Perl/Shorewall/Chains.pm index acbfeea71..719fce778 100644 --- a/Shorewall/Perl/Shorewall/Chains.pm +++ b/Shorewall/Perl/Shorewall/Chains.pm @@ -3370,6 +3370,13 @@ sub combine_dports { \@rules; } +my %bad_match = ( conntrack => 1, + dscp => 1, + ecn => 1, + mark => 1, + set => 1, + tos => 1, + u32 => 1 ); # # Delete duplicate rules from the passed chain. # @@ -3388,22 +3395,10 @@ sub delete_duplicates { my $duplicate = 0; if ( $baseref->{mode} == CAT_MODE ) { - $docheck = 1; - # - # We must not suppress duplicate rules that match on things that can - # be altered by other rules in the chain - # - for ( qw( mark connmark dscp tos set ecn u32 ) ) { - $docheck = 0, last if exists $baseref->{$_}; - } - } else { - $docheck = 0; - } - - if ( $docheck ) { my $ports1; - my @keys1 = sort( keys( %$baseref ) ); - my $rulenum = @_; + my @keys1 = sort( keys( %$baseref ) ); + my $rulenum = @_; + my $adjacent = 1; { RULE: @@ -3419,12 +3414,24 @@ sub delete_duplicates { my $keynum = 0; - for my $key ( @keys1 ) { - next RULE unless $key eq $keys2[$keynum++]; - next RULE unless compare_values( $baseref->{$key}, $ruleref->{$key} ); + if ( $adjacent > 0 ) { + for my $key ( @keys1 ) { + next RULE unless $key eq $keys2[$keynum++]; + next RULE unless compare_values( $baseref->{$key}, $ruleref->{$key} ); + } + } else { + for my $key ( @keys1 ) { + last RULE if $bad_match{$key}; + next RULE unless $key eq $keys2[$keynum++]; + next RULE unless compare_values( $baseref->{$key}, $ruleref->{$key} ); + } } $duplicate = 1; + $adjacent++; + + } continue { + $adjacent--; } } } diff --git a/Shorewall/manpages/shorewall.conf.xml b/Shorewall/manpages/shorewall.conf.xml index 6ce4a3d48..3315a3e35 100644 --- a/Shorewall/manpages/shorewall.conf.xml +++ b/Shorewall/manpages/shorewall.conf.xml @@ -1725,8 +1725,13 @@ net all DROP infothen the chain name is 'net2all' comments are replaced by 'and others'. Beginning in Shorewall 4.5.10, this option also suppresses - duplicate rules in a chain that don't include mark, connmark, - dscp, tos, set, ecn or u32 matches. + duplicate adjacent rules and duplicate non-adjacent rules that + don't include mark, connmark, dscp, ecn, set, tos + or u32 matches. diff --git a/Shorewall6/manpages/shorewall6.conf.xml b/Shorewall6/manpages/shorewall6.conf.xml index 06bb0b857..6976ec74a 100644 --- a/Shorewall6/manpages/shorewall6.conf.xml +++ b/Shorewall6/manpages/shorewall6.conf.xml @@ -1526,8 +1526,13 @@ net all DROP infothen the chain name is 'net2all' comments are replaced by 'and others'. Beginning in Shorewall 4.5.10, this option also suppresses - duplicate rules in a chain that don't include mark, connmark, - dscp, tos, set, ecn or u32 matches. + duplicate adjacent rules and duplicate non-adjacent rules that + don't include mark, connmark, dscp, ecn, set, tos + or u32 matches.