diff --git a/Shorewall/Perl/Shorewall/Providers.pm b/Shorewall/Perl/Shorewall/Providers.pm index 384d6f196..3fc04f090 100644 --- a/Shorewall/Perl/Shorewall/Providers.pm +++ b/Shorewall/Perl/Shorewall/Providers.pm @@ -337,24 +337,32 @@ sub balance_fallback_route( $$$$ ) { } } -sub start_provider( $$$ ) { - my ($table, $number, $test ) = @_; +sub start_provider( $$$$ ) { + my ($what, $table, $number, $test ) = @_; - emit "\n#\n# Add Provider $table ($number)\n#"; + emit "\n#\n# Add $what $table ($number)\n#"; + + if ( $number ) { + emit "start_provider_$table() {"; + } else { + emit "start_interface_$table() {"; + } - emit "start_provider_$table() {"; push_indent; emit $test; push_indent; - emit "qt ip -$family route flush table $number"; - emit "echo \"qt \$IP -$family route flush table $number\" > \${VARDIR}/undo_${table}_routing"; + if ( $number ) { + emit "qt ip -$family route flush table $number"; + emit "echo \"qt \$IP -$family route flush table $number\" > \${VARDIR}/undo_${table}_routing"; + } } # # Process a record in the providers file # -sub process_a_provider() { +sub process_a_provider( $ ) { + my $pseudo = $_[0]; # When true, this is an optional interface that we are treating somewhat like a provider. my ($table, $number, $mark, $duplicate, $interface, $gateway, $options, $copy ) = split_line 'providers file', { table => 0, number => 1, mark => 2, duplicate => 3, interface => 4, gateway => 5, options => 6, copy => 7 }; @@ -362,17 +370,20 @@ sub process_a_provider() { fatal_error "Duplicate provider ($table)" if $providers{$table}; fatal_error 'NAME must be specified' if $table eq '-'; - fatal_error "Invalid Provider Name ($table)" unless $table =~ /^[\w]+$/; - my $num = numeric_value $number; + unless ( $pseudo ) { + fatal_error "Invalid Provider Name ($table)" unless $table =~ /^[\w]+$/; - fatal_error 'NUMBER must be specified' if $number eq '-'; - fatal_error "Invalid Provider number ($number)" unless defined $num; + my $num = numeric_value $number; - $number = $num; + fatal_error 'NUMBER must be specified' if $number eq '-'; + fatal_error "Invalid Provider number ($number)" unless defined $num; - for my $providerref ( values %providers ) { - fatal_error "Duplicate provider number ($number)" if $providerref->{number} == $number; + $number = $num; + + for my $providerref ( values %providers ) { + fatal_error "Duplicate provider number ($number)" if $providerref->{number} == $number; + } } fatal_error 'INTERFACE must be specified' if $interface eq '-'; @@ -406,8 +417,15 @@ sub process_a_provider() { $gateway = ''; } - my ( $loose, $track, $balance , $default, $default_balance, $optional, $mtu, $tproxy , $local, $load ) = - (0, $config{TRACK_PROVIDERS}, 0 , 0, $config{USE_DEFAULT_RT} ? 1 : 0, interface_is_optional( $interface ), '' , 0 , 0, 0 ); + my ( $loose, $track, $balance, $default, $default_balance, $optional, $mtu, $tproxy, $local, $load, $what ); + + if ( $pseudo ) { + ( $loose, $track, $balance , $default, $default_balance, $optional, $mtu, $tproxy , $local, $load, $what ) = + ( 0, 0 , 0 , 0, 0, 1 , '' , 0 , 0, 0, 'interface'); + } else { + ( $loose, $track, $balance , $default, $default_balance, $optional, $mtu, $tproxy , $local, $load, $what )= + ( 0, $config{TRACK_PROVIDERS}, 0 , 0, $config{USE_DEFAULT_RT} ? 1 : 0, interface_is_optional( $interface ), '' , 0 , 0, 0, 'provider'); + } unless ( $options eq '-' ) { for my $option ( split_list $options, 'option' ) { @@ -517,7 +535,7 @@ sub process_a_provider() { } - unless ( $loose ) { + unless ( $loose || $pseudo ) { warning_message q(The 'proxyarp' option is dangerous when specified on a Provider interface) if get_interface_option( $interface, 'proxyarp' ); warning_message q(The 'proxyndp' option is dangerous when specified on a Provider interface) if get_interface_option( $interface, 'proxyndp' ); } @@ -555,10 +573,14 @@ sub process_a_provider() { local => $local , tproxy => $tproxy , load => $load , + pseudo => $pseudo , + what => $what , rules => [] , routes => [] , }; + $provider_interfaces{$interface} = $table unless $shared; + if ( $track ) { fatal_error "The 'track' option requires a numeric value in the MARK column" if $mark eq '-'; @@ -577,7 +599,20 @@ sub process_a_provider() { push @providers, $table; - progress_message " Provider \"$currentline\" $done"; + progress_message " Provider \"$currentline\" $done" unless $pseudo; +} + +# +# Emit a 'started' message +# +sub emit_started_message( $$$$$ ) { + my ( $spaces, $level, $pseudo, $name, $number ) = @_; + + if ( $pseudo ) { + emit qq(${spaces}progress_message${level} " Optional interface $name Started"); + } else { + emit qq(${spaces}progress_message${level} " Provider $name ($number) Started"); + } } # @@ -608,6 +643,9 @@ sub add_a_provider( $$ ) { my $local = $providerref->{local}; my $tproxy = $providerref->{tproxy}; my $load = $providerref->{load}; + my $pseudo = $providerref->{pseudo}; + my $what = $providerref->{what}; + my $label = $pseudo ? 'Optional Interface' : 'Provider'; my $dev = chain_base $physical; my $base = uc $dev; @@ -616,14 +654,16 @@ sub add_a_provider( $$ ) { if ( $shared ) { my $variable = $providers{$table}{mac} = get_interface_mac( $gateway, $interface , $table ); $realm = "realm $number"; - start_provider( $table, $number, qq(if interface_is_usable $physical && [ -n "$variable" ]; then) ); + start_provider( $label , $table, $number, qq(if interface_is_usable $physical && [ -n "$variable" ]; then) ); + } elsif ( $pseudo ) { + start_provider( $label , $table, $number, qq(if [ -n "\$SW_${base}_IS_USABLE" ]; then) ); } else { if ( $optional ) { - start_provider( $table, $number, qq(if [ -n "\$SW_${base}_IS_USABLE" ]; then) ); + start_provider( $label, $table , $number, qq(if [ -n "\$SW_${base}_IS_USABLE" ]; then) ); } elsif ( $gatewaycase eq 'detect' ) { - start_provider( $table, $number, qq(if interface_is_usable $physical && [ -n "$gateway" ]; then) ); + start_provider( $label, $table, $number, qq(if interface_is_usable $physical && [ -n "$gateway" ]; then) ); } else { - start_provider( $table, $number, "if interface_is_usable $physical; then" ); + start_provider( $label, $table, $number, "if interface_is_usable $physical; then" ); } $provider_interfaces{$interface} = $table; @@ -741,7 +781,7 @@ CEOF emit "qt \$IP -$family rule del from $address" if $config{DELETE_THEN_ADD}; emit( "run_ip rule add from $address pref 20000 table $number" , "echo \"qt \$IP -$family rule del from $address\" >> \${VARDIR}/undo_${table}_routing" ); - } else { + } elsif ( ! $pseudo ) { emit ( "find_interface_addresses $physical | while read address; do" ); emit ( " qt \$IP -$family rule del from \$address" ) if $config{DELETE_THEN_ADD}; emit ( " run_ip rule add from \$address pref 20000 table $number", @@ -804,15 +844,14 @@ CEOF emit( "setup_${dev}_tc" ) if $tcdevices->{$interface}; } - emit ( qq(progress_message2 " Provider $table ($number) Started") ); + emit_started_message( '', 2, $pseudo, $table, $number ); pop_indent; emit( 'else' ); - emit( qq( echo $weight > \${VARDIR}/${physical}_weight) , - qq( progress_message " Provider $table ($number) Started"), - qq(fi\n) - ); + emit( qq( echo $weight > \${VARDIR}/${physical}_weight) ); + emit_started_message( ' ', '', $pseudo, $table, $number ); + emit "fi\n"; } else { emit( qq(echo 0 > \${VARDIR}/${physical}.status) ); emit( qq(progress_message "Provider $table ($number) Started") ); @@ -829,6 +868,8 @@ CEOF if ( $optional ) { if ( $shared ) { emit ( "error_message \"WARNING: Gateway $gateway is not reachable -- Provider $table ($number) not Started\"" ); + } elsif ( $pseudo ) { + emit ( "error_message \"WARNING: Optional Interface $physical is not usable -- $table not Started\"" ); } else { emit ( "error_message \"WARNING: Interface $physical is not usable -- Provider $table ($number) not Started\"" ); } @@ -846,14 +887,14 @@ CEOF pop_indent; - emit '}'; # End of start_provider_$table(); + emit "} # End of start_${what}_${table}();"; if ( $optional ) { emit( '', '#', - "# Stop provider $table", + "# Stop $what $table", '#', - "stop_provider_$table() {" ); + "stop_${what}_${table}() {" ); push_indent; @@ -893,8 +934,13 @@ CEOF "qt \$TC qdisc del dev $physical ingress\n" ) if $tcdevices->{$interface}; } - emit( "echo 1 > \${VARDIR}/${physical}.status", - "progress_message2 \" Provider $table ($number) stopped\"" ); + emit( "echo 1 > \${VARDIR}/${physical}.status" ); + + if ( $pseudo ) { + emit( "progress_message2 \" Optional Interface $table stopped\"" ); + } else { + emit( "progress_message2 \" Provider $table ($number) stopped\"" ); + } pop_indent; @@ -1203,12 +1249,23 @@ sub process_providers( $ ) { my $tcdevices = shift; our $providers = 0; + our $pseudoproviders = 0; $lastmark = 0; if ( my $fn = open_file 'providers' ) { first_entry "$doing $fn..."; - process_a_provider, $providers++ while read_a_line( NORMAL_READ ); + process_a_provider(0), $providers++ while read_a_line( NORMAL_READ ); + } + # + # Treat optional interfaces as pseudo-providers + # + for ( grep interface_is_optional( $_ ) && ! $provider_interfaces{ $_ }, all_real_interfaces ) { + # + # TABLE NUMBER MARK DUPLICATE INTERFACE GATEWAY OPTIONS COPY + $currentline = "$_ 0 - - $_ - - -"; + # + process_a_provider(1), $pseudoproviders++; } if ( $providers ) { @@ -1231,17 +1288,19 @@ sub process_providers( $ ) { add_an_rtrule while read_a_line( NORMAL_READ ); } + } - $fn = open_file 'routes'; + if ( $providers || $pseudoproviders ) { + my $fn = open_file 'routes'; if ( $fn ) { first_entry "$doing $fn..."; emit ''; add_a_route while read_a_line( NORMAL_READ ); } - } - add_a_provider( $providers{$_}, $tcdevices ) for @providers; + add_a_provider( $providers{$_}, $tcdevices ) for @providers; + } emit << 'EOF';; @@ -1262,14 +1321,20 @@ EOF if ( $providerref->{optional} ) { if ( $providerref->{shared} || $providerref->{physical} eq $provider) { - emit "$provider})"; + emit "$provider)"; } else { emit( "$providerref->{physical}|$provider)" ); } - emit ( " if [ -z \"`\$IP -$family route ls table $providerref->{number}`\" ]; then", - " start_provider_$provider", - ' else', + if ( $providerref->{pseudo} ) { + emit ( " if [ ! -f \${VARDIR}/$product/undo_${provider}_routing ]; then", + " start_interface_$provider" ); + } else { + emit ( " if [ -z \"`\$IP -$family route ls table $providerref->{number}`\" ]; then", + " start_provider_$provider" ); + } + + emit ( ' else', " startup_error \"Interface $providerref->{physical} is already enabled\"", ' fi', ' ;;' @@ -1282,7 +1347,7 @@ EOF emit << 'EOF';; *) - startup_error "$g_interface is not an optional provider or provider interface" + startup_error "$g_interface is not an optional provider or interface" ;; esac @@ -1303,14 +1368,22 @@ EOF for my $provider (@providers ) { my $providerref = $providers{$provider}; - emit( "$providerref->{physical}|$provider)", - " if [ -n \"`\$IP -$family route ls table $providerref->{number}`\" ]; then", - " stop_provider_$provider", - ' else', - " startup_error \"Interface $providerref->{physical} is already disabled\"", - ' fi', - ' ;;' - ) if $providerref->{optional}; + if ( $provider eq $providerref->{physical} ) { + emit( "$provider)" ); + } else { + emit( "$providerref->{physical}|$provider)" ); + } + + emit( " if [ -n \"`\$IP -$family route ls table $providerref->{number}`\" ]; then" ); + + if ( $providerref->{optional} ) { + emit( " stop_$providerref->{what}_$provider", + ' else', + " startup_error \"Interface $providerref->{physical} is already disabled\"", + ' fi', + ' ;;' + ); + } } pop_indent; @@ -1342,7 +1415,7 @@ sub setup_providers() { emit ''; - emit "start_provider_$_" for @providers; + emit "start_$providers{$_}->{what}_$_" for @providers; emit ''; diff --git a/Shorewall/manpages/shorewall.xml b/Shorewall/manpages/shorewall.xml index 4c8d40d00..cb6d28312 100644 --- a/Shorewall/manpages/shorewall.xml +++ b/Shorewall/manpages/shorewall.xml @@ -897,6 +897,10 @@ or provider. Where more than one provider share a single network interface, a provider name must be given. + + Beginning with Shorewall 4.5.10, this command may be used with + any optional network interface. interface + may be either the logical or physical name of the interface. @@ -936,6 +940,10 @@ or provider. Where more than one provider share a single network interface, a provider name must be given. + + Beginning with Shorewall 4.5.10, this command may be used with + any optional network interface. interface + may be either the logical or physical name of the interface. diff --git a/Shorewall6/manpages/shorewall6.xml b/Shorewall6/manpages/shorewall6.xml index 8636416ab..a7c36c6bd 100644 --- a/Shorewall6/manpages/shorewall6.xml +++ b/Shorewall6/manpages/shorewall6.xml @@ -809,6 +809,10 @@ or provider. Where more than one provider share a single network interface, a provider name must be given. + + Beginning with Shorewall 4.5.10, this command may be used with + any optional network interface. interface + may be either the logical or physical name of the interface. @@ -848,6 +852,10 @@ or provider. Where more than one provider share a single network interface, a provider name must be given. + + Beginning with Shorewall 4.5.10, this command may be used with + any optional network interface. interface + may be either the logical or physical name of the interface. @@ -1105,7 +1113,7 @@ reset [chain, - ...] + ...] Resets the packet and byte counters in the specified