diff --git a/Shorewall/Perl/Shorewall/Chains.pm b/Shorewall/Perl/Shorewall/Chains.pm index 7174d7578..09022187c 100644 --- a/Shorewall/Perl/Shorewall/Chains.pm +++ b/Shorewall/Perl/Shorewall/Chains.pm @@ -260,6 +260,7 @@ our %EXPORT_TAGS = ( get_interface_gateway get_interface_mac have_global_variables + have_address_variables set_global_variables save_dynamic_chains load_ipsets @@ -5604,6 +5605,8 @@ sub have_ipset_rules() { sub get_interface_address( $ ); +sub get_interface_gateway ( $;$ ); + sub record_runtime_address( $$;$ ) { my ( $addrtype, $interface, $protect ) = @_; @@ -6693,11 +6696,10 @@ sub get_interface_gateway ( $;$ ) { $global_variables |= ALL_COMMANDS; if ( interface_is_optional $logical ) { - $interfacegateways{$interface} = qq([ -n "\$$variable" ] || $variable=\$($routine $interface)\n); + $interfacegateways{$interface} = qq([ -n "\$$variable" ] || $variable=\$($routine $interface)); } else { $interfacegateways{$interface} = qq([ -n "\$$variable" ] || $variable=\$($routine $interface) -[ -n "\$$variable" ] || startup_error "Unable to detect the gateway through interface $interface" -); +[ -n "\$$variable" ] || startup_error "Unable to detect the gateway through interface $interface"); } $protect ? "\${$variable:-" . NILIP . '}' : "\$$variable"; @@ -6803,16 +6805,40 @@ sub have_global_variables() { have_capability( 'ADDRTYPE' ) ? $global_variables : $global_variables | NOT_RESTORE; } +sub have_address_variables() { + ( keys %interfaceaddr || keys %interfacemacs || keys %interfacegateways ); +} + # # Generate setting of run-time global shell variables # -sub set_global_variables( $ ) { +sub set_global_variables( $$ ) { - my $setall = shift; + my ( $setall, $conditional ) = @_; - emit $_ for values %interfaceaddr; - emit $_ for values %interfacegateways; - emit $_ for values %interfacemacs; + if ( $conditional ) { + my ( $interface, $code ); + + while ( ( $interface, $code ) = each %interfaceaddr ) { + emit( qq([ -z "\$interface" -o "\$interface" = "$interface" ] && $code) ); + } + + while ( ( $interface, $code ) = each %interfacegateways ) { + emit( qq(if [ -z "\$interface" -o "\$interface" = "$interface" ]; then) ); + push_indent; + emit( $code ); + pop_indent; + emit( qq(fi\n) ); + } + + while ( ( $interface, $code ) = each %interfacemacs ) { + emit( qq([ -z "\$interface" -o "\$interface" = "$interface" ] && $code) ); + } + } else { + emit $_ for values %interfaceaddr; + emit "$_\n" for values %interfacegateways; + emit $_ for values %interfacemacs; + } if ( $setall ) { emit $_ for values %interfaceaddrs; diff --git a/Shorewall/Perl/Shorewall/Compiler.pm b/Shorewall/Perl/Shorewall/Compiler.pm index 5991ecc00..d3b09e65a 100644 --- a/Shorewall/Perl/Shorewall/Compiler.pm +++ b/Shorewall/Perl/Shorewall/Compiler.pm @@ -274,10 +274,21 @@ sub generate_script_2() { 'detect_configuration()', '{' ); - my $global_variables = have_global_variables; + my $global_variables = have_global_variables; + my $optional_interfaces = find_interfaces_by_option( 'optional' ); push_indent; + if ( have_address_variables || @$optional_interfaces ) { + emit( 'local interface', + '', + 'interface="$1"', + '' + ); + } + + map_provider_to_interface if have_providers; + if ( $global_variables ) { if ( $global_variables & NOT_RESTORE ) { @@ -292,7 +303,7 @@ sub generate_script_2() { if ( $global_variables == ( ALL_COMMANDS | NOT_RESTORE ) ) { - set_global_variables(0); + set_global_variables(0, 0); handle_optional_interfaces(0); } @@ -306,7 +317,7 @@ sub generate_script_2() { push_indent; } - set_global_variables(1); + set_global_variables(1,1); if ( $global_variables & NOT_RESTORE ) { handle_optional_interfaces(0); diff --git a/Shorewall/Perl/Shorewall/Providers.pm b/Shorewall/Perl/Shorewall/Providers.pm index a2e661b28..ed2a063d6 100644 --- a/Shorewall/Perl/Shorewall/Providers.pm +++ b/Shorewall/Perl/Shorewall/Providers.pm @@ -44,6 +44,7 @@ our @EXPORT = qw( process_providers compile_updown setup_load_distribution have_providers + map_provider_to_interface ); our @EXPORT_OK = qw( initialize provider_realm ); our $VERSION = '4.4_24'; @@ -1588,6 +1589,35 @@ sub have_providers() { return our $providers; } +sub map_provider_to_interface() { + + my $haveoptional; + + for my $providerref ( values %providers ) { + if ( $providerref->{optional} ) { + unless ( $haveoptional++ ) { + emit( 'if [ -n "$interface" ]; then', + ' case $interface in' ); + + push_indent; + push_indent; + } + + emit( $providerref->{provider} . ')', + ' interface=' . $providerref->{physical}, + ' ;;' ); + } + } + + if ( $haveoptional ) { + pop_indent; + pop_indent; + emit( ' esac', + "fi\n" + ); + } +} + sub setup_providers() { our $providers; @@ -1945,12 +1975,12 @@ sub handle_optional_interfaces( $ ) { # # Just an optional interface, or provider and interface are the same # - emit qq(if [ -z "\$1" -o "\$1" = "$physical" ]; then); + emit qq(if [ -z "\$interface" -o "\$interface" = "$physical" ]; then); } else { # # Provider # - emit qq(if [ -z "\$1" -o "\$1" = "$physical" -o "\$1" = "$provider" ]; then); + emit qq(if [ -z "\$interface" -o "\$interface" = "$physical" ]; then); } push_indent; @@ -1967,7 +1997,7 @@ sub handle_optional_interfaces( $ ) { pop_indent; - emit( 'fi' ); + emit( "fi\n" ); emit( ';;' ), pop_indent if $wildcards; }