diff --git a/Shorewall/Perl/Shorewall/ARP.pm b/Shorewall/Perl/Shorewall/ARP.pm
index 1fcad2c62..77f6457e3 100644
--- a/Shorewall/Perl/Shorewall/ARP.pm
+++ b/Shorewall/Perl/Shorewall/ARP.pm
@@ -278,7 +278,7 @@ sub create_arptables_load( $ ) {
'if [ $? != 0 ]; then',
qq( fatal_error "arptables-restore Failed. Input is in \${VARDIR}/.arptables-input"),
"fi\n",
- "run_ip neigh flush nud noarp nud stale nud reachable\n",
+ "run_ip neigh flush nud stale nud reachable\n",
);
pop_indent;
diff --git a/Shorewall/Perl/Shorewall/Chains.pm b/Shorewall/Perl/Shorewall/Chains.pm
index 6ae34bcce..f16b53fca 100644
--- a/Shorewall/Perl/Shorewall/Chains.pm
+++ b/Shorewall/Perl/Shorewall/Chains.pm
@@ -407,7 +407,7 @@ use constant {
use constant { OPTIMIZE_MASK => OPTIMIZE_POLICY_MASK | OPTIMIZE_RULESET_MASK };
-use constant { DONT_OPTIMIZE => 1 , DONT_DELETE => 2, DONT_MOVE => 4 };
+use constant { DONT_OPTIMIZE => 1 , DONT_DELETE => 2, DONT_MOVE => 4, RETURNS => 8, RETURNS_DONT_MOVE => 12 };
our %dscpmap = ( CS0 => 0x00,
CS1 => 0x08,
@@ -462,6 +462,9 @@ use constant { NULL_MODE => 0 , # Emitting neither shell commands nor iptables
CMD_MODE => 2 }; # Emitting shell commands.
our $mode;
+#
+# A reference to this rule is returned when we try to push a rule onto a 'complete' chain
+#
our $dummyrule = { simple => 1, mode => CAT_MODE };
#
@@ -664,9 +667,7 @@ sub initialize( $$$ ) {
%isocodes = ();
%nfobjects = ();
%switches = ();
- #
- # Initialize this here so we can make it dynamic without moving the initialization
- #
+
%terminating = ( ACCEPT => 1,
DROP => 1,
RETURN => 1,
@@ -680,6 +681,7 @@ sub initialize( $$$ ) {
NOTRACK => 1,
REDIRECT => 1,
RAWDNAT => 1,
+ RAWSNAT => 1,
REJECT => 1,
SAME => 1,
SNAT => 1,
@@ -1036,7 +1038,7 @@ sub push_rule( $$ ) {
push @{$chainref->{rules}}, $ruleref;
$chainref->{referenced} = 1;
- $chainref->{optflags} |= DONT_MOVE if ( $ruleref->{target} || '' ) eq 'RETURN';
+ $chainref->{optflags} |= RETURNS_DONT_MOVE if ( $ruleref->{target} || '' ) eq 'RETURN';
trace( $chainref, 'A', @{$chainref->{rules}}, "-A $chainref->{name} $_[1]" ) if $debug;
$chainref->{complete} = 1 if $complete;
@@ -1053,7 +1055,7 @@ sub add_trule( $$ ) {
assert( reftype $ruleref , $ruleref );
push @{$chainref->{rules}}, $ruleref;
$chainref->{referenced} = 1;
- $chainref->{optflags} |= DONT_MOVE if ( $ruleref->{target} || '' ) eq 'RETURN';
+ $chainref->{optflags} |= RETURNS_DONT_MOVE if ( $ruleref->{target} || '' ) eq 'RETURN';
trace( $chainref, 'A', @{$chainref->{rules}}, format_rule( $chainref, $ruleref ) ) if $debug;
@@ -1233,7 +1235,7 @@ sub push_irule( $$$;@ ) {
if ( $jump ) {
$ruleref->{jump} = $jump;
$ruleref->{target} = $target;
- $chainref->{optflags} |= DONT_MOVE if $target eq 'RETURN';
+ $chainref->{optflags} |= RETURNS_DONT_MOVE if $target eq 'RETURN';
$ruleref->{targetopts} = $targetopts if $targetopts;
} else {
$ruleref->{target} = '';
@@ -2850,6 +2852,7 @@ sub optimize_level4( $$ ) {
# The search continues until no short chains remain
# Chains with 'DONT_OPTIMIZE' are exempted from optimization
#
+
while ( $progress ) {
$progress = 0;
$passes++;
@@ -2888,100 +2891,112 @@ sub optimize_level4( $$ ) {
delete_references $chainref;
$progress = 1;
}
- } elsif ( $numrules == 1) {
- my $firstrule = $chainref->{rules}[0];
- #
- # Chain has a single rule
- #
- if ( $firstrule ->{simple} ) {
- #
- # 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 copy its rules to the built-in
- #
- if ( conditionally_copy_rules $chainref, $firstrule->{target} ) {
- #
- # Target was a user chain -- rules moved
- #
- $progress = 1;
- } else {
- #
- # Target was a built-in. Ignore this chain in follow-on passes
- #
- $chainref->{optflags} |= DONT_OPTIMIZE;
- }
- } elsif ( ( $firstrule->{target} || '' ) eq 'RETURN' ) {
- #
- # A chain with a single 'RETURN' rule -- get rid of it
- #
- delete_chain_and_references( $chainref );
- } else {
- #
- # Replace all references to this chain with references to the target
- #
- replace_references $chainref, $firstrule->{target}, $firstrule->{targetopts};
- $progress = 1;
- }
- } elsif ( $firstrule->{target} ) {
- #
- # Not so easy -- the rule contains matches
- #
- if ( $chainref->{builtin} || ! $globals{KLUDGEFREE} || $firstrule->{policy} ) {
- #
- # This case requires a new rule merging algorithm. Ignore this chain for
- # now on.
- #
- $chainref->{optflags} |= DONT_OPTIMIZE;
- } else {
- #
- # Replace references to this chain with the target and add the matches
- #
- $progress = 1 if replace_references1 $chainref, $firstrule;
- }
- }
} else {
#
- # Chain has more than one rule. If the last rule is a simple jump, then delete
- # all immediately preceding rules that have the same target
+ # The chain has rules -- determine if it is terminating
#
- my $rulesref = $chainref->{rules};
- my $lastref = $rulesref->[-1];
+ my $name = $chainref->{name};
+ my $lastref = $chainref->{rules}[-1];
- if ( $lastref->{simple} && $lastref->{target} && ! $lastref->{targetopts} ) {
- my $target = $lastref->{target};
- my $count = 0;
- my $rule = @$rulesref - 1;
+ unless ( $chainref->{optflags} & RETURNS || $terminating{$name} ) {
+ $progress = 1 if $terminating{$name} = ( ( $terminating{$lastref->{target} || ''} ) || ( $lastref->{jump} || '' ) eq 'g' );
+ }
- pop @$rulesref; #Pop the last simple rule
+ if ( $numrules == 1) {
+ #
+ # Chain has a single rule
+ #
+ my $firstrule = $lastref;
- while ( @$rulesref ) {
- my $rule1ref = $rulesref->[-1];
-
- last unless ( $rule1ref->{target} || '' ) eq $target && ! $rule1ref->{targetopts};
-
- trace ( $chainref, 'D', $rule, $rule1ref ) if $debug;
-
- pop @$rulesref;
- $progress = 1;
- $count++;
- $rule--;
- }
-
- if ( @$rulesref || ! $chainref->{builtin} || $target !~ /^(?:ACCEPT|DROP|REJECT)$/ ) {
- push @$rulesref, $lastref; # Restore the last simple rule
- } else {
+ if ( $firstrule ->{simple} ) {
#
- #empty builtin chain -- change it's policy
+ # Easy case -- the rule is a simple jump
#
- $chainref->{policy} = $target;
- trace( $chainref, 'P', undef, 'ACCEPT' ) if $debug;
- $count++;
+ if ( $chainref->{builtin} ) {
+ #
+ # A built-in chain. If the target is a user chain without 'dont_move',
+ # we can copy its rules to the built-in
+ #
+ if ( conditionally_copy_rules $chainref, $firstrule->{target} ) {
+ #
+ # Target was a user chain -- rules moved
+ #
+ $progress = 1;
+ } else {
+ #
+ # Target was a built-in. Ignore this chain in follow-on passes
+ #
+ $chainref->{optflags} |= DONT_OPTIMIZE;
+ }
+ } elsif ( ( $firstrule->{target} || '' ) eq 'RETURN' ) {
+ #
+ # A chain with a single 'RETURN' rule -- get rid of it
+ #
+ delete_chain_and_references( $chainref );
+ } else {
+ #
+ # Replace all references to this chain with references to the target
+ #
+ replace_references $chainref, $firstrule->{target}, $firstrule->{targetopts};
+ $progress = 1;
+ }
+ } elsif ( $firstrule->{target} ) {
+ #
+ # Not so easy -- the rule contains matches
+ #
+ if ( $chainref->{builtin} || ! $globals{KLUDGEFREE} || $firstrule->{policy} ) {
+ #
+ # This case requires a new rule merging algorithm. Ignore this chain for
+ # now on.
+ #
+ $chainref->{optflags} |= DONT_OPTIMIZE;
+ } else {
+ #
+ # Replace references to this chain with the target and add the matches
+ #
+ $progress = 1 if replace_references1 $chainref, $firstrule;
+ }
}
+ } else {
+ #
+ # Chain has more than one rule. If the last rule is a simple jump, then delete
+ # all immediately preceding rules that have the same target
+ #
+ my $rulesref = $chainref->{rules};
- progress_message " $count $target rules deleted from chain $chainref->{name}" if $count;
+ if ( $lastref->{simple} && $lastref->{target} && ! $lastref->{targetopts} ) {
+ my $target = $lastref->{target};
+ my $count = 0;
+ my $rule = @$rulesref - 1;
+
+ pop @$rulesref; #Pop the last simple rule
+
+ while ( @$rulesref ) {
+ my $rule1ref = $rulesref->[-1];
+
+ last unless ( $rule1ref->{target} || '' ) eq $target && ! $rule1ref->{targetopts};
+
+ trace ( $chainref, 'D', $rule, $rule1ref ) if $debug;
+
+ pop @$rulesref;
+ $progress = 1;
+ $count++;
+ $rule--;
+ }
+
+ if ( @$rulesref || ! $chainref->{builtin} || $target !~ /^(?:ACCEPT|DROP|REJECT)$/ ) {
+ push @$rulesref, $lastref; # Restore the last simple rule
+ } else {
+ #
+ #empty builtin chain -- change it's policy
+ #
+ $chainref->{policy} = $target;
+ trace( $chainref, 'P', undef, 'ACCEPT' ) if $debug;
+ $count++;
+ }
+
+ progress_message " $count $target rules deleted from chain $name" if $count;
+ }
}
}
}
diff --git a/Shorewall/Perl/Shorewall/Nat.pm b/Shorewall/Perl/Shorewall/Nat.pm
index d9730e1d7..2c5a6b4c1 100644
--- a/Shorewall/Perl/Shorewall/Nat.pm
+++ b/Shorewall/Perl/Shorewall/Nat.pm
@@ -724,8 +724,6 @@ sub handle_nonat_rule( $$$$$$$$$$ ) {
}
}
- set_optflags( $nonat_chain, DONT_MOVE | DONT_OPTIMIZE ) if $tgt eq 'RETURN';
-
expand_rule( $nonat_chain ,
PREROUTE_RESTRICT ,
$rule ,
diff --git a/Shorewall/Perl/Shorewall/Rules.pm b/Shorewall/Perl/Shorewall/Rules.pm
index 122535d2a..95c0a1f47 100644
--- a/Shorewall/Perl/Shorewall/Rules.pm
+++ b/Shorewall/Perl/Shorewall/Rules.pm
@@ -2475,8 +2475,6 @@ sub process_rule1 ( $$$$$$$$$$$$$$$$$$ ) {
if ( $actiontype & ACTION ) {
$action = $usedactions{$normalized_target}{name};
$loglevel = '';
- } else {
- set_optflags( $chainref , DONT_MOVE | DONT_OPTIMIZE ) if $action eq 'RETURN';
}
if ( $origdest ) {
diff --git a/Shorewall/Perl/lib.core b/Shorewall/Perl/lib.core
index 9d48337a2..923806a87 100644
--- a/Shorewall/Perl/lib.core
+++ b/Shorewall/Perl/lib.core
@@ -216,8 +216,8 @@ get_routed_networks() # $1 = interface name, $2-n = Fatal error message
delete_tc1()
{
clear_one_tc() {
- $TC qdisc del dev $1 root 2> /dev/null
- $TC qdisc del dev $1 ingress 2> /dev/null
+ $TC qdisc del dev ${1%@*} root 2> /dev/null
+ $TC qdisc del dev ${1%@*} ingress 2> /dev/null
}
diff --git a/Shorewall/manpages/shorewall-tcrules.xml b/Shorewall/manpages/shorewall-tcrules.xml
index a6bc173fa..a2f8d4aa0 100644
--- a/Shorewall/manpages/shorewall-tcrules.xml
+++ b/Shorewall/manpages/shorewall-tcrules.xml
@@ -1051,10 +1051,10 @@ Normal-Service => 0x00
role="bold">:[max]]
- Optional - packet Length. This field, if present allow you to
- match the length of a packet against a specific value or range of
- values. You must have iptables length support for this to work. A
- range is specified in the form
+ Optional - packet payload length. This field, if present allow
+ you to match the length of a packet payload (Layer 4 data ) against
+ a specific value or range of values. You must have iptables length
+ support for this to work. A range is specified in the form
min:max where either
min or max (but not both)
may be omitted. If min is omitted, then 0 is
diff --git a/Shorewall6/manpages/shorewall6-tcrules.xml b/Shorewall6/manpages/shorewall6-tcrules.xml
index c545b3695..6ac580ee4 100644
--- a/Shorewall6/manpages/shorewall6-tcrules.xml
+++ b/Shorewall6/manpages/shorewall6-tcrules.xml
@@ -913,10 +913,10 @@ Normal-Service => 0x00
role="bold">:[max]]
- Optional packet Length. This field, if present allow you to
- match the length of a packet against a specific value or range of
- values. You must have ip6tables length support for this to work. A
- range is specified in the form
+ Optional - packet payload length. This field, if present allow
+ you to match the length of a packet payload (Layer 4 data ) against
+ a specific value or range of values. You must have iptables length
+ support for this to work. A range is specified in the form
min:max where either
min or max (but not both)
may be omitted. If min is omitted, then 0 is
diff --git a/docs/configuration_file_basics.xml b/docs/configuration_file_basics.xml
index dfef73b20..fc70b3f45 100644
--- a/docs/configuration_file_basics.xml
+++ b/docs/configuration_file_basics.xml
@@ -142,10 +142,16 @@
- /etc/shorewall/blacklist - lists
+ /etc/shorewall/blacklist - Deprecated in
+ favor of /etc/shorewall/blrules. Lists
blacklisted IP/subnet/MAC addresses.
+
+ /etc/shorewall/blrules — Added in
+ Shorewall 4.5.0. Define blacklisting and whitelisting.
+
+
/etc/shorewall/init - commands that you
wish to execute at the beginning of a shorewall start
@@ -258,6 +264,11 @@
start/restart when LOAD_HELPERS_ONLY=Yes in
shorewall.conf.
+
+
+ /usr/share/arprules — Added in Shorewall
+ 4.5.12. Allows specification of arptables rules.
+ If you need to change a file in
@@ -297,6 +308,12 @@
# This is a comment
ACCEPT net $FW tcp www #This is an end-of-line comment
+
+
+ If a comment ends with a backslash ("\"), the next line will also
+ be treated as a comment. See Line
+ Continuation below.
+
@@ -516,6 +533,19 @@ ACCEPT net:\
continuation line does not end with a comma or colon, the leading white
space in the last line is not ignored.
+
+
+ A trailing backslash is not ignored in a comment. So the continued
+ rule above can be commented out with a single '#' as follows:
+
+ #ACTION SOURCE DEST PROTO DEST
+# PORT(S)
+#ACCEPT net:\
+ 206.124.146.177,\
+ 206.124.146.178,\
+ 206.124.146.180\
+ dmz tcp 873
+