diff --git a/Shorewall/Perl/Shorewall/Chains.pm b/Shorewall/Perl/Shorewall/Chains.pm index a8d4ba2f5..448d5723c 100644 --- a/Shorewall/Perl/Shorewall/Chains.pm +++ b/Shorewall/Perl/Shorewall/Chains.pm @@ -68,6 +68,8 @@ our %EXPORT_TAGS = ( OUTPUT_RESTRICT POSTROUTE_RESTRICT ALL_RESTRICT + ALL_COMMANDS + NOT_RESTORE add_command add_commands @@ -148,6 +150,7 @@ our %EXPORT_TAGS = ( get_interface_acasts get_interface_gateway get_interface_mac + have_global_variables set_global_variables create_netfilter_load create_chainlist_reload @@ -241,6 +244,10 @@ our $exclseq; our $iprangematch; our $chainseq; +our $global_variables; + +use constant { ALL_COMMANDS => 1, NOT_RESTORE => 2 }; + our %interfaceaddr; our %interfaceaddrs; our %interfacenets; @@ -338,6 +345,8 @@ sub initialize( $ ) { %interfaceacasts = (); %interfacegateways = (); + $global_variables = 0; + } INIT { @@ -2014,6 +2023,8 @@ sub get_interface_address ( $ ) { my $variable = interface_address( $interface ); my $function = interface_is_optional( $interface ) ? 'find_first_interface_address_if_any' : 'find_first_interface_address'; + $global_variables |= ALL_COMMANDS; + $interfaceaddr{$interface} = "$variable=\$($function $interface)\n"; "\$$variable"; @@ -2035,6 +2046,8 @@ sub get_interface_bcasts ( $ ) { my $variable = interface_bcasts( $interface ); + $global_variables |= NOT_RESTORE; + $interfacebcasts{$interface} = qq($variable="\$(get_interface_bcasts $interface) 255.255.255.255"); "\$$variable"; @@ -2054,6 +2067,8 @@ sub interface_acasts( $ ) { sub get_interface_acasts ( $ ) { my ( $interface ) = $_[0]; + $global_variables |= NOT_RESTORE; + my $variable = interface_acasts( $interface ); $interfaceacasts{$interface} = qq($variable="\$(get_interface_acasts $interface) ff00::/10"); @@ -2079,11 +2094,13 @@ sub get_interface_gateway ( $ ) { my $routine = $config{USE_DEFAULT_RT} ? 'detect_dynamic_gateway' : 'detect_gateway'; + $global_variables |= ALL_COMMANDS; + if ( interface_is_optional $interface ) { $interfacegateways{$interface} = qq([ -n "\$$variable" ] || $variable=\$($routine $interface)\n); } else { $interfacegateways{$interface} = qq([ -n "\$$variable" ] || $variable=\$($routine $interface) -[ -n "\$$variable" ] || fatal_error "Unable to detect the gateway through interface $interface" +[ -n "\$$variable" ] || startup_error "Unable to detect the gateway through interface $interface" ); } @@ -2106,11 +2123,13 @@ sub get_interface_addresses ( $ ) { my $variable = interface_addresses( $interface ); + $global_variables |= NOT_RESTORE; + if ( interface_is_optional $interface ) { $interfaceaddrs{$interface} = qq($variable=\$(find_interface_addresses $interface)\n); } else { $interfaceaddrs{$interface} = qq($variable=\$(find_interface_addresses $interface) -[ -n "\$$variable" ] || fatal_error "Unable to determine the IP address(es) of $interface" +[ -n "\$$variable" ] || startup_error "Unable to determine the IP address(es) of $interface" ); } @@ -2133,11 +2152,13 @@ sub get_interface_nets ( $ ) { my $variable = interface_nets( $interface ); + $global_variables |= ALL_COMMANDS; + if ( interface_is_optional $interface ) { $interfacenets{$interface} = qq($variable=\$(get_routed_networks $interface)\n); } else { $interfacenets{$interface} = qq($variable=\$(get_routed_networks $interface) -[ -n "\$$variable" ] || fatal_error "Unable to determine the routes through interface \\"$interface\\"" +[ -n "\$$variable" ] || startup_error "Unable to determine the routes through interface \\"$interface\\"" ); } @@ -2161,86 +2182,50 @@ sub get_interface_mac( $$$ ) { my $variable = interface_mac( $interface , $table ); + $global_variables |= NOT_RESTORE; + if ( interface_is_optional $interface ) { $interfacemacs{$table} = qq($variable=\$(find_mac $ipaddr $interface)\n); } else { $interfacemacs{$table} = qq($variable=\$(find_mac $ipaddr $interface) -[ -n "\$$variable" ] || fatal_error "Unable to determine the MAC address of $ipaddr through interface \\"$interface\\"" +[ -n "\$$variable" ] || startup_error "Unable to determine the MAC address of $ipaddr through interface \\"$interface\\"" ); } "\$$variable"; } +sub have_global_variables() { + $capabilities{ADDRTYPE} ? $global_variables : $global_variables | NOT_RESTORE; +} + # # Generate setting of run-time global shell variables # -sub emit_comment() { - emit ( '#', - '# Establish the values of shell variables used in the following function calls', - '#' ); - our $emitted_comment = 1; -} -sub emit_test() { - emit ( 'if [ "$COMMAND" != restore ]; then' , - '' ); - push_indent; - our $emitted_test = 1; -} +sub set_global_variables( $ ) { + + my $setall = shift; -sub set_global_variables() { + emit $_ for values %interfaceaddr; + emit $_ for values %interfacegateways; + emit $_ for values %interfacemacs; + + if ( $setall ) { + emit $_ for values %interfaceaddrs; + emit $_ for values %interfacenets; - our ( $emitted_comment, $emitted_test ) = (0, 0); + unless ( $capabilities{ADDRTYPE} ) { - for ( values %interfaceaddr ) { - emit_comment unless $emitted_comment; - emit $_; - } - - for ( values %interfacegateways ) { - emit_comment unless $emitted_comment; - emit $_; - } - - for ( values %interfacemacs ) { - emit_comment unless $emitted_comment; - emit $_; - } - - for ( values %interfaceaddrs ) { - emit_comment unless $emitted_comment; - emit_test unless $emitted_test; - emit $_; - } - - for ( values %interfacenets ) { - emit_comment unless $emitted_comment; - emit_test unless $emitted_test; - emit $_; - } - - unless ( $capabilities{ADDRTYPE} ) { - emit_comment unless $emitted_comment; - emit_test unless $emitted_test; - - if ( $family == F_IPV4 ) { - emit 'ALL_BCASTS="$(get_all_bcasts) 255.255.255.255"'; - - for ( values %interfacebcasts ) { - emit $_; - } - } else { - emit 'ALL_ACASTS="$(get_all_acasts)"'; - - for ( values %interfaceacasts ) { - emit $_; + if ( $family == F_IPV4 ) { + emit 'ALL_BCASTS="$(get_all_bcasts) 255.255.255.255"'; + emit $_ for values %interfacebcasts; + } else { + emit 'ALL_ACASTS="$(get_all_acasts)"'; + emit $_ for values %interfaceacasts; } } } - - pop_indent, emit "fi\n" if $emitted_test; - } ################################################################################################################ @@ -2736,7 +2721,10 @@ sub create_netfilter_load( $ ) { $mode = NULL_MODE; - emit ( 'setup_netfilter()', + emit ( '#', + '# Create the input to iptables-restore/ip6tables-restore and pass that input to the utility', + '#', + 'setup_netfilter()', '{' ); diff --git a/Shorewall/Perl/Shorewall/Compiler.pm b/Shorewall/Perl/Shorewall/Compiler.pm index 848ed7384..0217db9ef 100644 --- a/Shorewall/Perl/Shorewall/Compiler.pm +++ b/Shorewall/Perl/Shorewall/Compiler.pm @@ -75,11 +75,6 @@ sub reinitialize() { # First stage of script generation. # # Copy the prog.header to the generated script. -# Generate the various user-exit jacket functions. -# Generate the 'initialize()' function. -# -# Note: This function is not called when $command eq 'check'. So it must have no side effects other -# than those related to writing to the object file. sub generate_script_1() { @@ -95,6 +90,18 @@ sub generate_script_1() { copy $globals{SHAREDIRPL} . 'prog.header6'; } } +} + +# +# Second stage of script generation. +# +# Generate the various user-exit jacket functions. +# Generate the 'initialize()' function. +# +# Note: This function is not called when $command eq 'check'. So it must have no side effects other +# than those related to writing to the object file. + +sub generate_script_2() { for my $exit qw/init isusable start tcclear started stop stopped clear refresh refreshed restored/ { emit "\nrun_${exit}_exit() {"; @@ -227,9 +234,50 @@ sub generate_script_1() { '[ -d ${VARDIR} ] || mkdir -p ${VARDIR}' ); + my $global_variables = have_global_variables; + + if ( $global_variables ) { + emit( '' , + '#' , + '# Set global variables holding detected IP information' , + '#' , + 'case $COMMAND in' ); + + push_indent; + + if ( $global_variables & NOT_RESTORE ) { + emit( 'start|restart|refresh)' ); + } else { + emit( 'start|restart|refresh|restore)' ); + } + + push_indent; + + set_global_variables(1); + + emit ';;'; + + if ( $global_variables == ( ALL_COMMANDS | NOT_RESTORE ) ) { + pop_indent; + + emit 'restore)'; + + push_indent; + + set_global_variables(0); + + emit ';;'; + } + + pop_indent; + pop_indent; + + emit ( 'esac' ) , + } + pop_indent; - emit "}\n"; # End of initialize() + emit "\n}\n"; # End of initialize() } @@ -579,6 +627,7 @@ EOF # # Final stage of script generation. # +# Copy prog.functions to the object file. # Generate code for loading the various files in /var/lib/shorewall[-lite] # Generate code to add IP addresses under ADD_IP_ALIASES and ADD_SNAT_ALIASES # @@ -588,7 +637,15 @@ EOF # Note: This function is not called when $command eq 'check'. So it must have no side effects other # than those related to writing to the object file. # -sub generate_script_2($) { +sub generate_script_3($) { + + unless ( $test ) { + if ( $family == F_IPV4 ) { + copy $globals{SHAREDIRPL} . 'prog.functions'; + } else { + copy $globals{SHAREDIRPL} . 'prog.functions6'; + } + } if ( $family == F_IPV4 ) { progress_message2 "Creating iptables-restore input..."; @@ -730,10 +787,6 @@ sub generate_script_2($) { emit qq(delete_tc1\n) if $config{CLEAR_TC}; - set_global_variables; - - emit ''; - emit( 'setup_common_rules', '' ); emit( 'setup_routing_and_traffic_shaping', '' ); @@ -957,26 +1010,18 @@ sub compiler { # (Produces no output to the compiled script) # setup_notrack; - # - # I N I T I A L I Z E - # (Writes the initialize() function to the compiled script) - # + enable_object; - + unless ( $command eq 'check' ) { + # + # Place Header in the object + # generate_script_1; # # C O M M O N _ R U L E S # (Writes the setup_common_rules() function to the compiled script) # - unless ( $test ) { - if ( $family == F_IPV4 ) { - copy $globals{SHAREDIRPL} . 'prog.functions'; - } else { - copy $globals{SHAREDIRPL} . 'prog.functions6'; - } - } - emit( "\n#", '# Setup Common Rules (/proc)', '#', @@ -1112,6 +1157,11 @@ sub compiler { } } else { enable_object; + # + # I N I T I A L I Z E + # (Writes the initialize() function to the compiled script) + # + generate_script_2; # S T O P _ F I R E W A L L # (Writes the stop_firewall() function to the compiled script) # @@ -1120,7 +1170,7 @@ sub compiler { # N E T F I L T E R L O A D # (Produces setup_netfilter(), chainlist_reload() and define_firewall() ) # - generate_script_2( $chains ); + generate_script_3( $chains ); # # Close, rename and secure the object # diff --git a/Shorewall/Perl/prog.header b/Shorewall/Perl/prog.header index a73bd32ff..fd10d173e 100644 --- a/Shorewall/Perl/prog.header +++ b/Shorewall/Perl/prog.header @@ -580,7 +580,7 @@ find_first_interface_address() # $1 = interface # # If there wasn't one, bail out now # - [ -n "$addr" ] || fatal_error "Can't determine the IP address of $1" + [ -n "$addr" ] || startup_error "Can't determine the IP address of $1" # # Strip off the trailing VLSM mask (or the peer IP in case of a P-t-P link) # along with everything else on the line diff --git a/Shorewall/Perl/prog.header6 b/Shorewall/Perl/prog.header6 index 2cf1adba5..1432c3d95 100644 --- a/Shorewall/Perl/prog.header6 +++ b/Shorewall/Perl/prog.header6 @@ -446,7 +446,7 @@ find_first_interface_address() # $1 = interface # # If there wasn't one, bail out now # - [ -n "$addr" ] || fatal_error "Can't determine the IPv6 address of $1" + [ -n "$addr" ] || startup_error "Can't determine the IPv6 address of $1" # # Strip off the trailing VLSM mask (or the peer IP in case of a P-t-P link) # along with everything else on the line