Detect IP configuration early in start/restart so that stopping the fireawall isn't necessary in the case of failure.

Signed-off-by: Tom Eastep <teastep@shorewall.net>

git-svn-id: https://shorewall.svn.sourceforge.net/svnroot/shorewall/trunk@9722 fbd18981-670d-0410-9b5c-8dc0c1a9a2bb
This commit is contained in:
teastep 2009-03-21 16:45:27 +00:00
parent 072067c8d2
commit bb8e562d18
4 changed files with 129 additions and 91 deletions

View File

@ -68,6 +68,8 @@ our %EXPORT_TAGS = (
OUTPUT_RESTRICT OUTPUT_RESTRICT
POSTROUTE_RESTRICT POSTROUTE_RESTRICT
ALL_RESTRICT ALL_RESTRICT
ALL_COMMANDS
NOT_RESTORE
add_command add_command
add_commands add_commands
@ -148,6 +150,7 @@ our %EXPORT_TAGS = (
get_interface_acasts get_interface_acasts
get_interface_gateway get_interface_gateway
get_interface_mac get_interface_mac
have_global_variables
set_global_variables set_global_variables
create_netfilter_load create_netfilter_load
create_chainlist_reload create_chainlist_reload
@ -241,6 +244,10 @@ our $exclseq;
our $iprangematch; our $iprangematch;
our $chainseq; our $chainseq;
our $global_variables;
use constant { ALL_COMMANDS => 1, NOT_RESTORE => 2 };
our %interfaceaddr; our %interfaceaddr;
our %interfaceaddrs; our %interfaceaddrs;
our %interfacenets; our %interfacenets;
@ -338,6 +345,8 @@ sub initialize( $ ) {
%interfaceacasts = (); %interfaceacasts = ();
%interfacegateways = (); %interfacegateways = ();
$global_variables = 0;
} }
INIT { INIT {
@ -2014,6 +2023,8 @@ sub get_interface_address ( $ ) {
my $variable = interface_address( $interface ); my $variable = interface_address( $interface );
my $function = interface_is_optional( $interface ) ? 'find_first_interface_address_if_any' : 'find_first_interface_address'; 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"; $interfaceaddr{$interface} = "$variable=\$($function $interface)\n";
"\$$variable"; "\$$variable";
@ -2035,6 +2046,8 @@ sub get_interface_bcasts ( $ ) {
my $variable = interface_bcasts( $interface ); my $variable = interface_bcasts( $interface );
$global_variables |= NOT_RESTORE;
$interfacebcasts{$interface} = qq($variable="\$(get_interface_bcasts $interface) 255.255.255.255"); $interfacebcasts{$interface} = qq($variable="\$(get_interface_bcasts $interface) 255.255.255.255");
"\$$variable"; "\$$variable";
@ -2054,6 +2067,8 @@ sub interface_acasts( $ ) {
sub get_interface_acasts ( $ ) { sub get_interface_acasts ( $ ) {
my ( $interface ) = $_[0]; my ( $interface ) = $_[0];
$global_variables |= NOT_RESTORE;
my $variable = interface_acasts( $interface ); my $variable = interface_acasts( $interface );
$interfaceacasts{$interface} = qq($variable="\$(get_interface_acasts $interface) ff00::/10"); $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'; my $routine = $config{USE_DEFAULT_RT} ? 'detect_dynamic_gateway' : 'detect_gateway';
$global_variables |= ALL_COMMANDS;
if ( interface_is_optional $interface ) { if ( interface_is_optional $interface ) {
$interfacegateways{$interface} = qq([ -n "\$$variable" ] || $variable=\$($routine $interface)\n); $interfacegateways{$interface} = qq([ -n "\$$variable" ] || $variable=\$($routine $interface)\n);
} else { } else {
$interfacegateways{$interface} = qq([ -n "\$$variable" ] || $variable=\$($routine $interface) $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 ); my $variable = interface_addresses( $interface );
$global_variables |= NOT_RESTORE;
if ( interface_is_optional $interface ) { if ( interface_is_optional $interface ) {
$interfaceaddrs{$interface} = qq($variable=\$(find_interface_addresses $interface)\n); $interfaceaddrs{$interface} = qq($variable=\$(find_interface_addresses $interface)\n);
} else { } else {
$interfaceaddrs{$interface} = qq($variable=\$(find_interface_addresses $interface) $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 ); my $variable = interface_nets( $interface );
$global_variables |= ALL_COMMANDS;
if ( interface_is_optional $interface ) { if ( interface_is_optional $interface ) {
$interfacenets{$interface} = qq($variable=\$(get_routed_networks $interface)\n); $interfacenets{$interface} = qq($variable=\$(get_routed_networks $interface)\n);
} else { } else {
$interfacenets{$interface} = qq($variable=\$(get_routed_networks $interface) $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 ); my $variable = interface_mac( $interface , $table );
$global_variables |= NOT_RESTORE;
if ( interface_is_optional $interface ) { if ( interface_is_optional $interface ) {
$interfacemacs{$table} = qq($variable=\$(find_mac $ipaddr $interface)\n); $interfacemacs{$table} = qq($variable=\$(find_mac $ipaddr $interface)\n);
} else { } else {
$interfacemacs{$table} = qq($variable=\$(find_mac $ipaddr $interface) $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"; "\$$variable";
} }
sub have_global_variables() {
$capabilities{ADDRTYPE} ? $global_variables : $global_variables | NOT_RESTORE;
}
# #
# Generate setting of run-time global shell variables # 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() { sub set_global_variables( $ ) {
emit ( 'if [ "$COMMAND" != restore ]; then' ,
'' ); my $setall = shift;
push_indent;
our $emitted_test = 1;
}
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 ) { if ( $family == F_IPV4 ) {
emit_comment unless $emitted_comment; emit 'ALL_BCASTS="$(get_all_bcasts) 255.255.255.255"';
emit $_; emit $_ for values %interfacebcasts;
} } else {
emit 'ALL_ACASTS="$(get_all_acasts)"';
for ( values %interfacegateways ) { emit $_ for values %interfaceacasts;
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 $_;
} }
} }
} }
pop_indent, emit "fi\n" if $emitted_test;
} }
################################################################################################################ ################################################################################################################
@ -2736,7 +2721,10 @@ sub create_netfilter_load( $ ) {
$mode = NULL_MODE; $mode = NULL_MODE;
emit ( 'setup_netfilter()', emit ( '#',
'# Create the input to iptables-restore/ip6tables-restore and pass that input to the utility',
'#',
'setup_netfilter()',
'{' '{'
); );

View File

@ -75,11 +75,6 @@ sub reinitialize() {
# First stage of script generation. # First stage of script generation.
# #
# Copy the prog.header to the generated script. # 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() { sub generate_script_1() {
@ -95,6 +90,18 @@ sub generate_script_1() {
copy $globals{SHAREDIRPL} . 'prog.header6'; 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/ { for my $exit qw/init isusable start tcclear started stop stopped clear refresh refreshed restored/ {
emit "\nrun_${exit}_exit() {"; emit "\nrun_${exit}_exit() {";
@ -227,9 +234,50 @@ sub generate_script_1() {
'[ -d ${VARDIR} ] || mkdir -p ${VARDIR}' '[ -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; pop_indent;
emit "}\n"; # End of initialize() emit "\n}\n"; # End of initialize()
} }
@ -579,6 +627,7 @@ EOF
# #
# Final stage of script generation. # 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 for loading the various files in /var/lib/shorewall[-lite]
# Generate code to add IP addresses under ADD_IP_ALIASES and ADD_SNAT_ALIASES # 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 # 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. # 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 ) { if ( $family == F_IPV4 ) {
progress_message2 "Creating iptables-restore input..."; progress_message2 "Creating iptables-restore input...";
@ -730,10 +787,6 @@ sub generate_script_2($) {
emit qq(delete_tc1\n) if $config{CLEAR_TC}; emit qq(delete_tc1\n) if $config{CLEAR_TC};
set_global_variables;
emit '';
emit( 'setup_common_rules', '' ); emit( 'setup_common_rules', '' );
emit( 'setup_routing_and_traffic_shaping', '' ); emit( 'setup_routing_and_traffic_shaping', '' );
@ -957,26 +1010,18 @@ sub compiler {
# (Produces no output to the compiled script) # (Produces no output to the compiled script)
# #
setup_notrack; setup_notrack;
#
# I N I T I A L I Z E
# (Writes the initialize() function to the compiled script)
#
enable_object; enable_object;
unless ( $command eq 'check' ) { unless ( $command eq 'check' ) {
#
# Place Header in the object
#
generate_script_1; generate_script_1;
# #
# C O M M O N _ R U L E S # C O M M O N _ R U L E S
# (Writes the setup_common_rules() function to the compiled script) # (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#", emit( "\n#",
'# Setup Common Rules (/proc)', '# Setup Common Rules (/proc)',
'#', '#',
@ -1112,6 +1157,11 @@ sub compiler {
} }
} else { } else {
enable_object; 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 # S T O P _ F I R E W A L L
# (Writes the stop_firewall() function to the compiled script) # (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 # N E T F I L T E R L O A D
# (Produces setup_netfilter(), chainlist_reload() and define_firewall() ) # (Produces setup_netfilter(), chainlist_reload() and define_firewall() )
# #
generate_script_2( $chains ); generate_script_3( $chains );
# #
# Close, rename and secure the object # Close, rename and secure the object
# #

View File

@ -580,7 +580,7 @@ find_first_interface_address() # $1 = interface
# #
# If there wasn't one, bail out now # 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) # 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 # along with everything else on the line

View File

@ -446,7 +446,7 @@ find_first_interface_address() # $1 = interface
# #
# If there wasn't one, bail out now # 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) # 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 # along with everything else on the line