diff --git a/Shorewall-common/changelog.txt b/Shorewall-common/changelog.txt index 6d693ea38..1ddcf26f0 100644 --- a/Shorewall-common/changelog.txt +++ b/Shorewall-common/changelog.txt @@ -1,3 +1,5 @@ +Changes in 3.9.8 + Changes in 3.9.7 1) Clean up release notes. @@ -12,6 +14,13 @@ Changes in 3.9.7 6) Fix 'detect' in GATEWAY column of providers file. +8) Other bug fixes (see release notes). + +7) Fix action in 'logreject'. + +8) Allow macros to invoke macros outside of action bodies. + + Changes in 3.9.6 1) Fix parsing problems in protocol handling. diff --git a/Shorewall-common/releasenotes.txt b/Shorewall-common/releasenotes.txt index 284146e46..ae61e4420 100644 --- a/Shorewall-common/releasenotes.txt +++ b/Shorewall-common/releasenotes.txt @@ -76,6 +76,14 @@ Other changes in Shorewall 3.9.7. - Backslash. Probibited except as the last character on a line to denote line continuation. +3) Macros may now invoke other macros with the restriction that such + macros may not be invoked within an action body. + + When marcros are invoked recursively, the parameter passed to an + invocation are automatically propagated to lower level macros. + + Macro invocations may be nested to a maximum level of 5. + Migration Considerations: 1) You cannot simply upgrade your existing Shorewall package. You must diff --git a/Shorewall-perl/Shorewall/Actions.pm b/Shorewall-perl/Shorewall/Actions.pm index 1b3cb609d..f8cf2e2d2 100644 --- a/Shorewall-perl/Shorewall/Actions.pm +++ b/Shorewall-perl/Shorewall/Actions.pm @@ -461,7 +461,7 @@ sub process_action3( $$$$$ ) { if ( $mtarget =~ /^PARAM:?/ ) { fatal_error 'PARAM requires that a parameter be supplied in macro invocation' unless $param; - $mtarget = substitute_action $param, $mtarget; + $mtarget = substitute_param $param, $mtarget; } if ( $msource ) { diff --git a/Shorewall-perl/Shorewall/Macros.pm b/Shorewall-perl/Shorewall/Macros.pm index 7698664e4..55ffbfa0b 100644 --- a/Shorewall-perl/Shorewall/Macros.pm +++ b/Shorewall-perl/Shorewall/Macros.pm @@ -34,7 +34,7 @@ use strict; our @ISA = qw(Exporter); our @EXPORT = qw( find_macro split_action - substitute_action + substitute_param merge_macro_source_dest merge_macro_column @@ -76,11 +76,11 @@ sub split_action ( $ ) { # # Example: # -# substitute_action DNAT PARAM:info:FTP +# substitute_param DNAT PARAM:info:FTP # # produces "DNAT:info:FTP" # -sub substitute_action( $$ ) { +sub substitute_param( $$ ) { my ( $param, $action ) = @_; if ( $action =~ /:/ ) { diff --git a/Shorewall-perl/Shorewall/Rules.pm b/Shorewall-perl/Shorewall/Rules.pm index 830a2734e..435125c58 100644 --- a/Shorewall-perl/Shorewall/Rules.pm +++ b/Shorewall-perl/Shorewall/Rules.pm @@ -62,6 +62,8 @@ my @rule_chains; # my $sectioned = 0; +use constant { MAX_MACRO_NEST_LEVEL => 5 }; + sub process_tos() { my $chain = $capabilities{MANGLE_FORWARD} ? 'fortos' : 'pretos'; my $stdchain = $capabilities{MANGLE_FORWARD} ? 'FORWARD' : 'PREROUTING'; @@ -501,7 +503,7 @@ sub add_common_rules() { my $state = $config{BLACKLISTNEWONLY} ? '-m state --state NEW,INVALID ' : ''; for $interface ( @interfaces ) { - for $chain ( input_chain $interface , forward_chain $interface ) { + for $chain ( @{first_chains $interface} ) { add_rule new_standard_chain( $chain ) , "$state -j dynamic"; } @@ -615,7 +617,7 @@ sub add_common_rules() { new_standard_chain $chain; } - (new_chain 'nat' , $chain = dynamic_in($interface) )->{referenced} = 1; + mark_referenced( new_chain 'nat' , $chain = dynamic_in($interface) ); add_rule $filter_table->{input_chain $interface}, "-j $chain"; add_rule $filter_table->{forward_chain $interface}, '-j ' . dynamic_fwd $interface; @@ -628,7 +630,7 @@ sub add_common_rules() { if ( @$list ) { progress_message2 '$doing UPnP'; - (new_chain 'nat', 'UPnP')->{referenced} = 1; + mark_referenced( new_chain( 'nat', 'UPnP' ) ); for $interface ( @$list ) { add_rule $nat_table->{PREROUTING} , "-i $interface -j UPnP"; @@ -784,8 +786,6 @@ sub process_rule1 ( $$$$$$$$$$ ); sub process_macro ( $$$$$$$$$$$$ ) { my ($macrofile, $target, $param, $source, $dest, $proto, $ports, $sports, $origdest, $rate, $user, $mark ) = @_; - my $standard = ( $macrofile =~ /^($globals{SHAREDIR})/ ); - progress_message "..Expanding Macro $macrofile..."; push_open $macrofile; @@ -797,15 +797,15 @@ sub process_macro ( $$$$$$$$$$$$ ) { $mtarget = merge_levels $target, $mtarget; if ( $mtarget =~ /^PARAM:?/ ) { - fatal_error 'PARAM requires that a parameter be supplied in macro invocation' unless $param; - $mtarget = substitute_action $param, $mtarget; + fatal_error 'PARAM requires a parameter to be supplied in macro invocation' unless $param ne ''; + $mtarget = substitute_param $param, $mtarget; } my $action = isolate_basic_target $mtarget; - my $actiontype = $targets{$action} || 0; + my $actiontype = $targets{$action} || find_macro( $action ); unless ( $actiontype & ACTION ) { - fatal_error "Invalid Action ($mtarget)" unless $actiontype & ( STANDARD + NATRULE ); + fatal_error "Invalid Action ($mtarget) in macro" unless $actiontype & ( STANDARD + NATRULE + MACRO ); } if ( $msource ) { @@ -852,6 +852,10 @@ sub process_macro ( $$$$$$$$$$$$ ) { progress_message '..End Macro' } +my $macro_nest_level = 0; +my $current_param = ''; +my @param_stack; + # # Once a rule has been completely resolved by macro expansion and wildcard (source and/or dest zone == 'all'), it is processed by this function. # @@ -862,6 +866,8 @@ sub process_rule1 ( $$$$$$$$$$ ) { my $rule = ''; my $actionchainref; + $param = '' unless defined $param; + # # Determine the validity of the action # @@ -871,11 +877,18 @@ sub process_rule1 ( $$$$$$$$$$ ) { if ( $actiontype == MACRO ) { # - # We will be called recursively for each rule in the macro body + # Will call process_rule1() recursively for each rule in the macro body # + fatal_error "Macro invocations nested too deeply" if ++$macro_nest_level > MAX_MACRO_NEST_LEVEL; + + if ( $param ne '' ) { + push @param_stack, $current_param; + $current_param = $param; + } + process_macro( $macros{$basictarget}, $target , - $param , + $current_param, $source, $dest, $proto, @@ -885,6 +898,11 @@ sub process_rule1 ( $$$$$$$$$$ ) { $ratelimit, $user, $mark ); + + $macro_nest_level--; + + $current_param = pop @param_stack if $param ne ''; + return; } #