Verify that interfaces in the providers file are known; unify 'optional' settings

git-svn-id: https://shorewall.svn.sourceforge.net/svnroot/shorewall/trunk@7680 fbd18981-670d-0410-9b5c-8dc0c1a9a2bb
This commit is contained in:
teastep 2007-11-17 16:48:25 +00:00
parent 43bde8c079
commit 8673ac70dd
4 changed files with 84 additions and 23 deletions

View File

@ -125,6 +125,7 @@ our %EXPORT_TAGS = (
get_interface_address get_interface_address
get_interface_addresses get_interface_addresses
get_interface_bcasts get_interface_bcasts
get_interface_gateway
get_interface_mac get_interface_mac
set_global_variables set_global_variables
create_netfilter_load create_netfilter_load
@ -219,7 +220,9 @@ our $chainseq;
our %interfaceaddr; our %interfaceaddr;
our %interfaceaddrs; our %interfaceaddrs;
our %interfacenets; our %interfacenets;
our %interfacemacs;
our %interfacebcasts; our %interfacebcasts;
our %interfacegateways;
our @builtins = qw(PREROUTING INPUT FORWARD OUTPUT POSTROUTING); our @builtins = qw(PREROUTING INPUT FORWARD OUTPUT POSTROUTING);
@ -315,10 +318,12 @@ sub initialize() {
# #
# Keep track of which interfaces have active 'address', 'addresses' and 'networks' variables # Keep track of which interfaces have active 'address', 'addresses' and 'networks' variables
# #
%interfaceaddr = (); %interfaceaddr = ();
%interfaceaddrs = (); %interfaceaddrs = ();
%interfacenets = (); %interfacenets = ();
%interfacebcasts = (); %interfacemacs = ();
%interfacebcasts = ();
%interfacegateways = ();
} }
INIT { INIT {
@ -1467,7 +1472,7 @@ sub mysplit( $ ) {
# #
sub interface_address( $ ) { sub interface_address( $ ) {
my $variable = chain_base( $_[0] ) . '_address'; my $variable = chain_base( $_[0] ) . '_address';
"\U$variable"; uc $variable;
} }
# #
@ -1479,7 +1484,7 @@ 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';
$interfaceaddr{$interface} = "$variable=\$($function $interface)"; $interfaceaddr{$interface} = "$variable=\$($function $interface)\n";
"\$$variable"; "\$$variable";
} }
@ -1489,7 +1494,7 @@ sub get_interface_address ( $ ) {
# #
sub interface_bcasts( $ ) { sub interface_bcasts( $ ) {
my $variable = chain_base( $_[0] ) . '_bcasts'; my $variable = chain_base( $_[0] ) . '_bcasts';
"\U$variable"; uc $variable;
} }
# #
@ -1505,12 +1510,39 @@ sub get_interface_bcasts ( $ ) {
"\$$variable"; "\$$variable";
} }
#
# Returns the name of the shell variable holding the gateway through the passed interface
#
sub interface_gateway( $ ) {
my $variable = chain_base( $_[0] ) . '_gateway';
uc $variable;
}
#
# Record that the ruleset requires the gateway address on the passed interface
#
sub get_interface_gateway ( $ ) {
my ( $interface ) = $_[0];
my $variable = interface_gateway( $interface );
if ( interface_is_optional $interface ) {
$interfacegateways{$interface} = qq($variable=\$(detect_gateway $interface)\n);
} else {
$interfacegateways{$interface} = qq($variable=\$(detect_gateway $interface)
[ -n "\$$variable" ] || fatal_error "Unable to detect the gateway through interface $interface"
);
}
"\$$variable";
}
# #
# Returns the name of the shell variable holding the addresses of the passed interface # Returns the name of the shell variable holding the addresses of the passed interface
# #
sub interface_addresses( $ ) { sub interface_addresses( $ ) {
my $variable = chain_base( $_[0] ) . '_addresses'; my $variable = chain_base( $_[0] ) . '_addresses';
"\U$variable"; uc $variable;
} }
# #
@ -1537,7 +1569,7 @@ sub get_interface_addresses ( $ ) {
# #
sub interface_nets( $ ) { sub interface_nets( $ ) {
my $variable = chain_base( $_[0] ) . '_networks'; my $variable = chain_base( $_[0] ) . '_networks';
"\U$variable"; uc $variable;
} }
# #
@ -1564,19 +1596,25 @@ sub get_interface_nets ( $ ) {
# Returns the name of the shell variable holding the MAC address of the gateway for the passed provider out of the passed interface # Returns the name of the shell variable holding the MAC address of the gateway for the passed provider out of the passed interface
# #
sub interface_mac( $$ ) { sub interface_mac( $$ ) {
my $variable = join( '_' , chain_base( $_[0] ) , $_[1] , 'mac' ); my $variable = join( '_' , chain_base( $_[0] ) , chain_base( $_[1] ) , 'mac' );
uc $variable; uc $variable;
} }
# #
# Emit code to determine the MAC address of the passed gateway IP routed out of the passed interface for the passed provider number # Record the fact that the ruleset requires MAC address of the passed gateway IP routed out of the passed interface for the passed provider number
# #
sub get_interface_mac( $$$ ) { sub get_interface_mac( $$$ ) {
my ( $ipaddr, $interface , $table ) = @_; my ( $ipaddr, $interface , $table ) = @_;
my $variable = interface_mac( $interface , $table ); my $variable = interface_mac( $interface , $table );
emit qq($variable=\$(find_mac $ipaddr $interface)); 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\\""
);
}
"\$$variable"; "\$$variable";
} }
@ -1980,6 +2018,16 @@ sub set_global_variables() {
emit $_; emit $_;
} }
for ( values %interfacegateways ) {
emit_comment unless $emitted_comment;
emit $_;
}
for ( values %interfacemacs ) {
emit_comment unless $emitted_comment;
emit $_;
}
for ( values %interfaceaddrs ) { for ( values %interfaceaddrs ) {
emit_comment unless $emitted_comment; emit_comment unless $emitted_comment;
emit_test unless $emitted_test; emit_test unless $emitted_test;

View File

@ -198,6 +198,8 @@ sub add_a_provider( $$$$$$$$ ) {
fatal_error "Duplicate provider number ($number)" if $providerref->{number} == $number; fatal_error "Duplicate provider number ($number)" if $providerref->{number} == $number;
} }
fatal_error "Unknown Interface ($interface)" unless known_interface $interface;
my $provider = chain_base $table; my $provider = chain_base $table;
emit "#\n# Add Provider $table ($number)\n#"; emit "#\n# Add Provider $table ($number)\n#";
@ -213,11 +215,7 @@ sub add_a_provider( $$$$$$$$ ) {
if ( $gateway eq 'detect' ) { if ( $gateway eq 'detect' ) {
$variable = get_interface_address $interface; $variable = get_interface_address $interface;
emit ( "gateway=\$(detect_gateway $interface)\n", $gateway = get_interface_gateway $interface;
'if [ -z "$gateway" ]; then',
" fatal_error \"Unable to detect the gateway through interface $interface\"",
"fi\n" );
$gateway = '$gateway';
} elsif ( $gateway && $gateway ne '-' ) { } elsif ( $gateway && $gateway ne '-' ) {
validate_address $gateway, 0; validate_address $gateway, 0;
$variable = get_interface_address $interface; $variable = get_interface_address $interface;
@ -253,7 +251,7 @@ sub add_a_provider( $$$$$$$$ ) {
); );
} }
my ( $loose, $optional, $track, $shared, $balance ) = (0,0,0,0,0); my ( $loose, $track, $shared, $balance , $optional ) = (0,0,0,0,interface_is_optional( $interface ));
unless ( $options eq '-' ) { unless ( $options eq '-' ) {
for my $option ( split /,/, $options ) { for my $option ( split /,/, $options ) {
@ -266,6 +264,7 @@ sub add_a_provider( $$$$$$$$ ) {
} elsif ( $option eq 'loose' ) { } elsif ( $option eq 'loose' ) {
$loose = 1; $loose = 1;
} elsif ( $option eq 'optional' ) { } elsif ( $option eq 'optional' ) {
set_interface_option $interface, 'optional', 1;
$optional = 1; $optional = 1;
} elsif ( $option eq 'shared' ) { } elsif ( $option eq 'shared' ) {
require_capability 'REALM_MATCH', "The 'shared' option", "s"; require_capability 'REALM_MATCH', "The 'shared' option", "s";
@ -276,7 +275,13 @@ sub add_a_provider( $$$$$$$$ ) {
} }
} }
$providers{$table} = { provider => $table, number => $number , mark => $val , optional => $optional , interface => $interface , gateway => $gateway, shared => $shared }; $providers{$table} = { provider => $table,
number => $number ,
mark => $val ,
interface => $interface ,
optional => $optional ,
gateway => $gateway ,
shared => $shared };
if ( $track ) { if ( $track ) {
fatal_error "The 'track' option requires a numeric value in the MARK column" if $mark eq '-'; fatal_error "The 'track' option requires a numeric value in the MARK column" if $mark eq '-';
@ -415,7 +420,7 @@ sub add_an_rtrule( $$$$ ) {
emit ( "qt ip rule del $source $dest $priority" ) if $config{DELETE_THEN_ADD}; emit ( "qt ip rule del $source $dest $priority" ) if $config{DELETE_THEN_ADD};
my ( $base, $optional, $number ) = ( chain_base( $provider ), $providers{$provider}{optional} , $providers{$provider}{number} ); my ( $base, $optional, $number ) = ( chain_base( $provider ) , $providers{$provider}{optional} , $providers{$provider}{number} );
emit ( '', "if [ -n \$${base}_is_up ]; then" ), push_indent if $optional; emit ( '', "if [ -n \$${base}_is_up ]; then" ), push_indent if $optional;

View File

@ -59,6 +59,7 @@ our @EXPORT = qw( NOTHING
interface_is_optional interface_is_optional
find_interfaces_by_option find_interfaces_by_option
get_interface_option get_interface_option
set_interface_option
validate_hosts_file validate_hosts_file
find_hosts_by_option find_hosts_by_option
); );
@ -863,6 +864,15 @@ sub get_interface_option( $$ ) {
$interfaces{$interface}{options}{$option}; $interfaces{$interface}{options}{$option};
} }
#
# Set an option for an interface
#
sub set_interface_option( $$$ ) {
my ( $interface, $option, $value ) = @_;
$interfaces{$interface}{options}{$option} = $value;
}
# #
# Validates the hosts file. Generates entries in %zone{..}{hosts} # Validates the hosts file. Generates entries in %zone{..}{hosts}
# #

View File

@ -918,11 +918,9 @@ find_mac() # $1 = IP address, $2 = interface
\<*\>) \<*\>)
;; ;;
*) *)
[ -n "$result" ] && echo $result && return [ -n "$result" ] && echo $result
;; ;;
esac esac
fatal_error "Cannot determine the MAC address of $1 through $2"
} }
################################################################################ ################################################################################