Recursive Macros -- Phase I

git-svn-id: https://shorewall.svn.sourceforge.net/svnroot/shorewall/trunk@6332 fbd18981-670d-0410-9b5c-8dc0c1a9a2bb
This commit is contained in:
teastep 2007-05-12 18:13:11 +00:00
parent c8fa0fcde3
commit 13402f4da4
5 changed files with 50 additions and 15 deletions

View File

@ -1,3 +1,5 @@
Changes in 3.9.8
Changes in 3.9.7 Changes in 3.9.7
1) Clean up release notes. 1) Clean up release notes.
@ -12,6 +14,13 @@ Changes in 3.9.7
6) Fix 'detect' in GATEWAY column of providers file. 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 Changes in 3.9.6
1) Fix parsing problems in protocol handling. 1) Fix parsing problems in protocol handling.

View File

@ -76,6 +76,14 @@ Other changes in Shorewall 3.9.7.
- Backslash. Probibited except as the last character on a line to - Backslash. Probibited except as the last character on a line to
denote line continuation. 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: Migration Considerations:
1) You cannot simply upgrade your existing Shorewall package. You must 1) You cannot simply upgrade your existing Shorewall package. You must

View File

@ -461,7 +461,7 @@ sub process_action3( $$$$$ ) {
if ( $mtarget =~ /^PARAM:?/ ) { if ( $mtarget =~ /^PARAM:?/ ) {
fatal_error 'PARAM requires that a parameter be supplied in macro invocation' unless $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 ) { if ( $msource ) {

View File

@ -34,7 +34,7 @@ use strict;
our @ISA = qw(Exporter); our @ISA = qw(Exporter);
our @EXPORT = qw( find_macro our @EXPORT = qw( find_macro
split_action split_action
substitute_action substitute_param
merge_macro_source_dest merge_macro_source_dest
merge_macro_column merge_macro_column
@ -76,11 +76,11 @@ sub split_action ( $ ) {
# #
# Example: # Example:
# #
# substitute_action DNAT PARAM:info:FTP # substitute_param DNAT PARAM:info:FTP
# #
# produces "DNAT:info:FTP" # produces "DNAT:info:FTP"
# #
sub substitute_action( $$ ) { sub substitute_param( $$ ) {
my ( $param, $action ) = @_; my ( $param, $action ) = @_;
if ( $action =~ /:/ ) { if ( $action =~ /:/ ) {

View File

@ -62,6 +62,8 @@ my @rule_chains;
# #
my $sectioned = 0; my $sectioned = 0;
use constant { MAX_MACRO_NEST_LEVEL => 5 };
sub process_tos() { sub process_tos() {
my $chain = $capabilities{MANGLE_FORWARD} ? 'fortos' : 'pretos'; my $chain = $capabilities{MANGLE_FORWARD} ? 'fortos' : 'pretos';
my $stdchain = $capabilities{MANGLE_FORWARD} ? 'FORWARD' : 'PREROUTING'; my $stdchain = $capabilities{MANGLE_FORWARD} ? 'FORWARD' : 'PREROUTING';
@ -501,7 +503,7 @@ sub add_common_rules() {
my $state = $config{BLACKLISTNEWONLY} ? '-m state --state NEW,INVALID ' : ''; my $state = $config{BLACKLISTNEWONLY} ? '-m state --state NEW,INVALID ' : '';
for $interface ( @interfaces ) { 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"; add_rule new_standard_chain( $chain ) , "$state -j dynamic";
} }
@ -615,7 +617,7 @@ sub add_common_rules() {
new_standard_chain $chain; 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->{input_chain $interface}, "-j $chain";
add_rule $filter_table->{forward_chain $interface}, '-j ' . dynamic_fwd $interface; add_rule $filter_table->{forward_chain $interface}, '-j ' . dynamic_fwd $interface;
@ -628,7 +630,7 @@ sub add_common_rules() {
if ( @$list ) { if ( @$list ) {
progress_message2 '$doing UPnP'; progress_message2 '$doing UPnP';
(new_chain 'nat', 'UPnP')->{referenced} = 1; mark_referenced( new_chain( 'nat', 'UPnP' ) );
for $interface ( @$list ) { for $interface ( @$list ) {
add_rule $nat_table->{PREROUTING} , "-i $interface -j UPnP"; add_rule $nat_table->{PREROUTING} , "-i $interface -j UPnP";
@ -784,8 +786,6 @@ sub process_rule1 ( $$$$$$$$$$ );
sub process_macro ( $$$$$$$$$$$$ ) { sub process_macro ( $$$$$$$$$$$$ ) {
my ($macrofile, $target, $param, $source, $dest, $proto, $ports, $sports, $origdest, $rate, $user, $mark ) = @_; my ($macrofile, $target, $param, $source, $dest, $proto, $ports, $sports, $origdest, $rate, $user, $mark ) = @_;
my $standard = ( $macrofile =~ /^($globals{SHAREDIR})/ );
progress_message "..Expanding Macro $macrofile..."; progress_message "..Expanding Macro $macrofile...";
push_open $macrofile; push_open $macrofile;
@ -797,15 +797,15 @@ sub process_macro ( $$$$$$$$$$$$ ) {
$mtarget = merge_levels $target, $mtarget; $mtarget = merge_levels $target, $mtarget;
if ( $mtarget =~ /^PARAM:?/ ) { if ( $mtarget =~ /^PARAM:?/ ) {
fatal_error 'PARAM requires that a parameter be supplied in macro invocation' unless $param; fatal_error 'PARAM requires a parameter to be supplied in macro invocation' unless $param ne '';
$mtarget = substitute_action $param, $mtarget; $mtarget = substitute_param $param, $mtarget;
} }
my $action = isolate_basic_target $mtarget; my $action = isolate_basic_target $mtarget;
my $actiontype = $targets{$action} || 0; my $actiontype = $targets{$action} || find_macro( $action );
unless ( $actiontype & 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 ) { if ( $msource ) {
@ -852,6 +852,10 @@ sub process_macro ( $$$$$$$$$$$$ ) {
progress_message '..End 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. # 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 $rule = '';
my $actionchainref; my $actionchainref;
$param = '' unless defined $param;
# #
# Determine the validity of the action # Determine the validity of the action
# #
@ -871,11 +877,18 @@ sub process_rule1 ( $$$$$$$$$$ ) {
if ( $actiontype == MACRO ) { 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}, process_macro( $macros{$basictarget},
$target , $target ,
$param , $current_param,
$source, $source,
$dest, $dest,
$proto, $proto,
@ -885,6 +898,11 @@ sub process_rule1 ( $$$$$$$$$$ ) {
$ratelimit, $ratelimit,
$user, $user,
$mark ); $mark );
$macro_nest_level--;
$current_param = pop @param_stack if $param ne '';
return; return;
} }
# #