diff --git a/Shorewall/Macros/macro.template b/Shorewall/Macros/macro.template index a5fd284b5..c2f87aab9 100644 --- a/Shorewall/Macros/macro.template +++ b/Shorewall/Macros/macro.template @@ -71,6 +71,14 @@ # Remaining Any value in the rules file REPLACES the value # columns given in the macro file. # +# Multiple parameters may be passed to a macro. Within this file, $1 refers to the first parameter, +# $2 to the second an so on. $1 is a synonym for PARAM but may be used anywhere in the file whereas +# PARAM may only be used in the ACTION column. +# +# You can specify default values for parameters by using DEFAULT or DEFAULTS entry: +# +# DEFAULTS ,,... +# ####################################################################################################### # DO NOT REMOVE THE FOLLOWING LINE FORMAT 2 diff --git a/Shorewall/Perl/Shorewall/Rules.pm b/Shorewall/Perl/Shorewall/Rules.pm index 2c45ec607..1e5ecb642 100644 --- a/Shorewall/Perl/Shorewall/Rules.pm +++ b/Shorewall/Perl/Shorewall/Rules.pm @@ -307,6 +307,51 @@ sub use_policy_action( $ ); sub normalize_action( $$$ ); sub normalize_action_name( $ ); +sub process_default_action( $$$$ ) { + my ( $originalpolicy, $policy, $default, $level ) = @_; + + if ( supplied $default ) { + my $default_option = ( $policy =~ /_DEFAULT$/ ); + my ( $def, $param ) = get_target_param( $default ); + + if ( supplied $level ) { + validate_level( $level ); + } else { + $level = 'none'; + } + + if ( "\L$default" eq 'none' ) { + if ( supplied $param || ( supplied $level && $level ne 'none' ) ) { + if ( $default_option ) { + fatal_error "Invalid setting (originalpolicy) for $policy"; + } else { + fatal_error "Invalid policy ($originalpolicy)"; + } + } + + $default = 'none'; + } elsif ( $actions{$def} ) { + $default = supplied $param ? normalize_action( $def, $level, $param ) : + $level eq 'none' ? normalize_action_name $def : + normalize_action( $def, $level, '' ); + use_policy_action( $default ); + } elsif ( find_macro( $def ) ) { + $default = join( '.', 'macro', $def ) unless $default =~ /^macro./; + $default = "$def($param)" if supplied $param; + } elsif ( $default_option ) { + fatal_error "Unknown Action ($default) in $policy setting"; + } else { + fatal_error "Unknown Default Action ($default)"; + } + + $default = join( ':', $default, $level ) if $level ne 'none'; + } else { + $default = $default_actions{$policy} || 'none'; + } + + $default; +} + # # Process an entry in the policy file. # @@ -338,11 +383,11 @@ sub process_a_policy() { require_capability 'AUDIT_TARGET', ":audit", "s" if $audit; - my ( $policy, $default, $remainder ) = split( /:/, $originalpolicy, 3 ); + my ( $policy, $default, $level, $remainder ) = split( /:/, $originalpolicy, 4 ); fatal_error "Invalid or missing POLICY ($originalpolicy)" unless $policy; - fatal_error "Invalid default action ($default:$remainder)" if defined $remainder; + fatal_error "Invalid default action ($default:$level:$remainder)" if defined $remainder; ( $policy , my $queue ) = get_target_param $policy; @@ -352,28 +397,7 @@ sub process_a_policy() { fatal_error "A $policy policy may not be audited" unless $auditpolicies{$policy}; } - if ( $default ) { - my ( $def, $param ) = get_target_param( $default ); - - if ( "\L$default" eq 'none' ) { - $default = 'none'; - } elsif ( $actions{$def} ) { - $default = supplied $param ? normalize_action( $def, 'none', $param ) : normalize_action_name $def; - use_policy_action( $default ); - } elsif ( find_macro( $def ) ) { - $def = join( '.', 'macro', $def ) unless $default =~ /^macro./; - if ( supplied $param ) { - validate_level($param); - $default = join( ':', $def, $param ); - } else { - $default = $def; - } - } else { - fatal_error "Unknown Default Action ($default)"; - } - } else { - $default = $default_actions{$policy} || 'none'; - } + $default = process_default_action( $originalpolicy, $policy, $default, $level ); if ( defined $queue ) { fatal_error "Invalid policy ($policy($queue))" unless $policy eq 'NFQUEUE'; @@ -506,24 +530,9 @@ sub process_policies() my $action = $config{$option}; unless ( $action eq 'none' ) { - my ( $act, $param ) = get_target_param( $action ); - - if ( "\L$action" eq 'none' ) { - $action = 'none'; - } elsif ( $actions{$act} ) { - $action = supplied $param ? normalize_action( $act, 'none', $param ) : normalize_action_name $act; - use_policy_action( $action ); - } elsif ( find_macro( $act ) ) { - $action = join( '.', 'macro', $act ) unless $action =~ /^macro\./; - if ( supplied $param ) { - validate_level( $param ); - $action = join( ':', $action, $param ); - } - } elsif ( $targets{$act} ) { - fatal_error "Invalid setting ($action) for $option"; - } else { - fatal_error "Default Action $option=$action not found"; - } + my ( $default, $level, $remainder ) = split( /:/, $action, 3 ); + fatal_error "Invalid setting ( $action ) for $option" if supplied $remainder; + $action = process_default_action( $action, $option, $default, $level ); } $default_actions{$map{$option}} = $action; @@ -577,25 +586,27 @@ sub policy_rules( $$$$$ ) { # my ( $macro ) = split ':', $default; - process_macro( $macro, #Macro - $chainref, #Chain - $default, #Target - '', #Param - '-', #Source - '-', #Dest - '-', #Proto - '-', #Ports - '-', #Sports - '-', #Original Dest - '-', #Rate - '-', #User - '-', #Mark - '-', #ConnLimit - '-', #Time - '-', #Headers - '-', #Condition - '-', #Helper - 0, #Wildcard + ( $macro, my $param ) = get_target_param( $macro ); + + process_macro( $macro, #Macro + $chainref, #Chain + $default, #Target + $param || '', #Param + '-', #Source + '-', #Dest + '-', #Proto + '-', #Ports + '-', #Sports + '-', #Original Dest + '-', #Rate + '-', #User + '-', #Mark + '-', #ConnLimit + '-', #Time + '-', #Headers + '-', #Condition + '-', #Helper + 0, #Wildcard ); } else { # @@ -1607,6 +1618,10 @@ sub process_macro ($$$$$$$$$$$$$$$$$$$) { macro_comment $macro; + my $oldparms = push_action_params( $chainref, $param ); + + ( $param ) = get_action_params( 1 ); + my $macrofile = $macros{$macro}; progress_message "..Expanding Macro $macrofile..."; @@ -1651,8 +1666,9 @@ sub process_macro ($$$$$$$$$$$$$$$$$$$) { next; } - if ( $mtarget eq 'DEFAULT' ) { - $param = $msource unless supplied $param; + if ( $mtarget =~ /^DEFAULTS?$/ ) { + default_action_params( $macro, split_list( $msource, 'defaults' ) ); + ( $param ) = get_action_params( 1 ) unless supplied $param; next; } @@ -1729,6 +1745,8 @@ sub process_macro ($$$$$$$$$$$$$$$$$$$) { progress_message "..End Macro $macrofile"; + pop_action_params( $oldparms ); + clear_comment unless $nocomment; return $generated; @@ -1795,7 +1813,7 @@ sub process_rule1 ( $$$$$$$$$$$$$$$$$$ ) { my $actiontype = $targets{$basictarget} || find_macro ( $basictarget ); if ( $config{ MAPOLDACTIONS } ) { - ( $basictarget, $actiontype , $param ) = map_old_actions( $basictarget ) unless $actiontype || $param; + ( $basictarget, $actiontype , $param ) = map_old_actions( $basictarget ) unless $actiontype || supplied $param; } fatal_error "Unknown ACTION ($action)" unless $actiontype; diff --git a/Shorewall/manpages/shorewall-policy.xml b/Shorewall/manpages/shorewall-policy.xml index dbd48b4da..0904c98b8 100644 --- a/Shorewall/manpages/shorewall-policy.xml +++ b/Shorewall/manpages/shorewall-policy.xml @@ -91,7 +91,7 @@ role="bold">QUEUE|NFQUEUE[(queuenumber)]|NONE}[:{default-action-or-macro|:{default-action-or-macro[:level]|None}] @@ -123,10 +123,12 @@ - Both actions and macros can have parameters specified. In the - case of a macro, only one parameter is allowed and specifies the log - level to be applied to each bare LOG rule (e.g., a rule specifying - 'LOG' with no level or tag in the ACTION column). + Both actions and macros can have parameters specified. + + Beginning with Shorewall 4.5.10, the macro or action name can + be followed optionally by a colon and a log level. The level will be + applied to each rule in the action or macro body that does not + already have a log level. Possible actions are: diff --git a/Shorewall/manpages/shorewall.conf.xml b/Shorewall/manpages/shorewall.conf.xml index b848f9563..5a6f1e113 100644 --- a/Shorewall/manpages/shorewall.conf.xml +++ b/Shorewall/manpages/shorewall.conf.xml @@ -92,7 +92,7 @@ ACCEPT_DEFAULT={action|ACCEPT_DEFAULT={action[(parameters)][:level]|none} @@ -102,7 +102,7 @@ DROP_DEFAULT={action|DROP_DEFAULT={action[(parameters)][:level]|none} @@ -112,7 +112,7 @@ NFQUEUE_DEFAULT={action|NFQUEUE_DEFAULT={action[(parameters)][:level]|none} @@ -122,7 +122,7 @@ QUEUE_DEFAULT={action|QUEUE_DEFAULT={action[(parameters)][:level]|none} @@ -132,7 +132,7 @@ REJECT_DEFAULT={action|REJECT_DEFAULT={action[(parameters)][:level]|none} @@ -190,10 +190,15 @@ specify the name of the macro file (e.g., macro.macro-name). - You can pass parameters to the specified action or macro - (e.g., myaction(audit,DROP)). In the case of a - macro, only a single parameter may be passed; that parameter is - interpreted as the log level for rules in the macro body. + You can pass parameters to the + specified action or macro (e.g., + myaction(audit,DROP)). + + Beginning with Shorewall 4.5.10, the macro or action name can + be followed optionally by a colon and a log + level. The level will be applied to each + rule in the action or macro body that does not already have a log + level. diff --git a/Shorewall6/manpages/shorewall6-policy.xml b/Shorewall6/manpages/shorewall6-policy.xml index 86154322c..2ed83324e 100644 --- a/Shorewall6/manpages/shorewall6-policy.xml +++ b/Shorewall6/manpages/shorewall6-policy.xml @@ -123,10 +123,10 @@ - Both actions and macros can have parameters specified. In the - case of a macro, only one parameter is allowed and specifies the log - level to be applied to each bare LOG rule (e.g., a rule specifying - 'LOG' with no level or tag in the ACTION column). + Beginning with Shorewall 4.5.10, the macro or action name can + be followed optionally by a colon and a log level. The level will be + applied to each rule in the action or macro body that does not + already have a log level. Possible actions are: diff --git a/Shorewall6/manpages/shorewall6.conf.xml b/Shorewall6/manpages/shorewall6.conf.xml index 13a6c156a..9cb8ece89 100644 --- a/Shorewall6/manpages/shorewall6.conf.xml +++ b/Shorewall6/manpages/shorewall6.conf.xml @@ -78,7 +78,7 @@ ACCEPT_DEFAULT={action|ACCEPT_DEFAULT={action[(parameters)][:level]|none} @@ -88,7 +88,7 @@ DROP_DEFAULT={action|DROP_DEFAULT={action[(parameters)][:level]|none} @@ -98,7 +98,7 @@ NFQUEUE_DEFAULT={action|NFQUEUE_DEFAULT={action[(parameters)][:level]|none} @@ -108,7 +108,7 @@ QUEUE_DEFAULT={action|QUEUE_DEFAULT={action[(parameters)][:level]|none} @@ -118,7 +118,7 @@ REJECT_DEFAULT={action|REJECT_DEFAULT={action[(parameters)][:level]|none} @@ -168,10 +168,15 @@ specify the name of the macro file here (e.g., macro.macro-name). - You can pass parameters to the specified action or macro - (e.g., myaction(audit,DROP)). In the case of a - macro, only a single parameter may be passed; that parameter is - interpreted as the log level for rules in the macro body. + You can pass parameters to the + specified action or macro (e.g., + myaction(audit,DROP)). + + Beginning with Shorewall 4.5.10, the macro or action name can + be followed optionally by a colon and a log + level. The level will be applied to each + rule in the action or macro body that does not already have a log + level. diff --git a/docs/Macros.xml b/docs/Macros.xml index 94fc31c88..597b955b3 100644 --- a/docs/Macros.xml +++ b/docs/Macros.xml @@ -291,6 +291,21 @@ ACCEPT fw loc tcp 135,139,445 Beginning with Shorewall 4.5.10, macros may also be used as default actions. + + Also beginning with Shorewall 4.5.10, you may pass multiple + parameters in a macro invocation. Within the macro body, $1 expands to + the value of the first parameter, $2 expands to the value of the second + and so on. + + You can specify default values for parameters using a DEFAULT or + DEFAULTS line. + + DEFAULTS def1,def2,... + + where def1 is the default value for the + first parameter, def2 is the default value + for the second parameter and so on. You can specify an empty default + using '-' (e.g. DEFAULTS DROP,-,audit).