diff --git a/New/Shorewall/Chains.pm b/New/Shorewall/Chains.pm index 065a03aad..3facf2530 100644 --- a/New/Shorewall/Chains.pm +++ b/New/Shorewall/Chains.pm @@ -1216,20 +1216,63 @@ sub insertnatjump( $$$$ ) { my @builtins = qw(PREROUTING INPUT FORWARD OUTPUT POSTROUTING); +use constant { NULL_STATE => 0 , + CAT_STATE => 1 , + CMD_STATE => 2 }; + +my $state = NULL_STATE; + +sub emitr( $ ) { + my $rule = $_[0]; + + if ( substr( $rule, 0, 1 ) eq '~' ) { + # + # A command + # + unless ( $state == CMD_STATE ) { + emit_unindented "__EOF__\n" if $state == CAT_STATE; + $state = CMD_STATE; + } + + $rule =~ s/~//; + + emit $rule; + } else { + unless ( $state == CAT_STATE ) { + emit 'cat >&3 << __EOF__'; + $state = CAT_STATE; + } + + emit_unindented $rule; + } +} + sub create_netfilter_load() { + emit 'setup_netfilter()'; emit '{'; - emit( $slowstart ? ' iptables_slow_restore << __EOF__' : ' iptables-restore << __EOF__' ); + push_indent; + + if ( $slowstart ) { + emit 'TEMPFILE=$(mktempfile)'; + emit ''; + emit 'exec 3>>$OUTPUT'; + } else { + emit 'iptables-restore << __EOF__'; + $state = CAT_STATE; + } + + emit ''; for my $table qw/raw nat mangle filter/ { - emit "*$table"; + emitr "*$table"; my @chains; for my $chain ( @builtins ) { my $chainref = $chain_table{$table}{$chain}; if ( $chainref ) { - emit ":$chain $chainref->{policy} [0:0]"; + emitr ":$chain $chainref->{policy} [0:0]"; push @chains, $chainref; } } @@ -1237,7 +1280,7 @@ sub create_netfilter_load() { for my $chain ( grep $chain_table{$table}{$_}->{referenced} , ( sort keys %{$chain_table{$table}} ) ) { my $chainref = $chain_table{$table}{$chain}; unless ( $chainref->{builtin} ) { - emit ":$chainref->{name} - [0:0]"; + emitr ":$chainref->{name} - [0:0]"; push @chains, $chainref; } } @@ -1246,19 +1289,25 @@ sub create_netfilter_load() { my $name = $chainref->{name}; for my $rule ( @{$chainref->{rules}} ) { $rule = "-A $name $rule" unless substr( $rule, 0, 1) eq '~'; - emit_unindented $rule; + emitr $rule; } } - emit 'COMMIT'; + emitr 'COMMIT'; } - emit '__EOF__'; + emit_unindented '__EOF__' unless $state == CMD_STATE; emit ''; + + emit 'iptables-restore << $TEMPFILE' if $slowstart; emit 'if [ $? != 0 ]; then'; emit ' fatal_error "iptables-restore Failed"'; emit "fi\n"; + emit 'rm -f $TEMPFILE' if $slowstart; + + pop_indent; + emit "}\n"; } diff --git a/New/Shorewall/Nat.pm b/New/Shorewall/Nat.pm index 2ceacf37a..f3e347e12 100644 --- a/New/Shorewall/Nat.pm +++ b/New/Shorewall/Nat.pm @@ -342,7 +342,7 @@ sub do_one_nat( $$$$$ ) if ( $add_ip_aliases ) { unless ( $addresses_to_add{$external} ) { $addresses_to_add{$external} = 1; - push @addresses_to_add, "$external $interface"; + push @addresses_to_add, ( $external , $interface ); } } diff --git a/New/compiler.pl b/New/compiler.pl index d8e2f8b88..869fffad6 100755 --- a/New/compiler.pl +++ b/New/compiler.pl @@ -86,7 +86,8 @@ sub generate_script_1 { emit 'PRODUCT=\'Shorewall\''; emit '. /usr/share/shorewall/lib.base'; } - + + emit 'TEMPFILE='; emit ''; for my $exit qw/init start tcclear started stop stopped/ { @@ -115,8 +116,8 @@ sub generate_script_1 { emit ''; emit 'local version=$(cat ${SHAREDIR}/version)'; emit ''; - emit 'if [ ${SHOREWALL_LIBVERSION:-0} -lt 30203 ]; then'; - emit ' fatal_error "This script requires Shorewall version 3.3.3 or later; current version is $version"'; + emit 'if [ ${SHOREWALL_LIBVERSION:-0} -lt 30401 ]; then'; + emit ' fatal_error "This script requires Shorewall version 3.4.2 or later; current version is $version"'; emit 'fi'; emit '#'; emit '# These variables are required by the library functions called in this script'; @@ -533,28 +534,47 @@ sub generate_script_3() { emit "#\n# Start/Restart the Firewall\n#"; emit 'define_firewall() {'; - emit ' setup_routing_and_traffic_shaping;'; - emit ' setup_netfilter'; - emit ' restore_dynamic_rules'; - emit ' date > ${VARDIR}/restarted'; - emit ' run_start_exit'; - emit ' run_iptables -N shorewall'; - emit ' set_state "Started"'; - emit ' run_started_exit'; - emit ''; - emit ' cp -f $(my_pathname) ${VARDIR}/.restore + push_indent; + emit 'setup_routing_and_traffic_shaping; - case \$COMMAND in - start) - logger -p kern.info "$PRODUCT started" - ;; - restart) - logger -p kern.info "$PRODUCT restarted" - ;; - restore) - logger -p kern.info "$PRODUCT restored" - ;; - esac'; +if [ $COMMAND = restore ]; then + iptables_save_file=${VARDIR}/$(basename $0)-iptables + if [ -f $iptables_save_file ]; then + iptables-restore < $iptables_save_file + else + fatal_error "$iptables_save_file does not exist" + exit 2 + fi + set_state "Started" +else + setup_netfilter + restore_dynamic_rules + run_start_exit + $IPTABLES -N shorewall + set_state "Started" + run_started_exit + + cp -f $(my_pathname) ${VARDIR}/.restore +fi + +date > ${VARDIR}/restarted + +case $COMMAND in + start) + logger -p kern.info "$PRODUCT started" + ;; + restart) + logger -p kern.info "$PRODUCT restarted" + ;; + refresh) + logger -p kern.info "$PRODUCT refreshed" + ;; + restore) + logger -p kern.info "$PRODUCT restored" + ;; +esac'; + + pop_indent; emit "}\n"; diff --git a/New/prog.functions b/New/prog.functions index b1c1e3ac6..2271fa2ef 100644 --- a/New/prog.functions +++ b/New/prog.functions @@ -58,6 +58,7 @@ fatal_error() { echo " ERROR: $@" >&2 stop_firewall + [ -n "$TEMPFILE" ] && rm -f $TEMPFILE exit 2 }