mirror of
https://gitlab.com/shorewall/code.git
synced 2024-12-15 19:01:19 +01:00
Re-implement optional interface handling
Signed-off-by: Tom Eastep <teastep@shorewall.net>
This commit is contained in:
parent
d94f2cc86d
commit
57c54af6ed
@ -2437,7 +2437,7 @@ sub do_length( $ ) {
|
||||
#
|
||||
sub match_source_dev( $ ) {
|
||||
my $interface = shift;
|
||||
my $interfaceref = known_interface( $interface );
|
||||
my $interfaceref = known_interface( $interface, 0 );
|
||||
$interface = $interfaceref->{physical} if $interfaceref;
|
||||
return '' if $interface eq '+';
|
||||
if ( $interfaceref && $interfaceref->{options}{port} ) {
|
||||
@ -2452,7 +2452,7 @@ sub match_source_dev( $ ) {
|
||||
#
|
||||
sub match_dest_dev( $ ) {
|
||||
my $interface = shift;
|
||||
my $interfaceref = known_interface( $interface );
|
||||
my $interfaceref = known_interface( $interface, 0 );
|
||||
$interface = $interfaceref->{physical} if $interfaceref;
|
||||
return '' if $interface eq '+';
|
||||
if ( $interfaceref && $interfaceref->{options}{port} ) {
|
||||
@ -3251,7 +3251,7 @@ sub expand_rule( $$$$$$$$$$;$ )
|
||||
# Verify Interface, if any
|
||||
#
|
||||
if ( $iiface ) {
|
||||
fatal_error "Unknown Interface ($iiface)" unless known_interface $iiface;
|
||||
fatal_error "Unknown Interface ($iiface)" unless known_interface( $iiface, 0 );
|
||||
|
||||
if ( $restriction & POSTROUTE_RESTRICT ) {
|
||||
#
|
||||
@ -3341,7 +3341,7 @@ sub expand_rule( $$$$$$$$$$;$ )
|
||||
# Verify Destination Interface, if any
|
||||
#
|
||||
if ( $diface ) {
|
||||
fatal_error "Unknown Interface ($diface)" unless known_interface $diface;
|
||||
fatal_error "Unknown Interface ($diface)" unless known_interface( $diface, 0 );
|
||||
|
||||
if ( $restriction & PREROUTE_RESTRICT ) {
|
||||
#
|
||||
|
@ -142,7 +142,7 @@ sub process_one_masq( )
|
||||
$rule .= "-m realm --realm $realm ";
|
||||
}
|
||||
|
||||
fatal_error "Unknown interface ($interface)" unless my $interfaceref = known_interface( $interface );
|
||||
fatal_error "Unknown interface ($interface)" unless my $interfaceref = known_interface( $interface, 0 );
|
||||
|
||||
unless ( $interfaceref->{root} ) {
|
||||
$rule .= match_dest_dev( $interface );
|
||||
@ -314,7 +314,7 @@ sub do_one_nat( $$$$$ )
|
||||
my $rulein = '';
|
||||
my $ruleout = '';
|
||||
|
||||
fatal_error "Unknown interface ($interface)" unless my $interfaceref = known_interface( $interface );
|
||||
fatal_error "Unknown interface ($interface)" unless my $interfaceref = known_interface( $interface, 0 );
|
||||
|
||||
unless ( $interfaceref->{root} ) {
|
||||
$rulein = match_source_dev $interface;
|
||||
@ -408,7 +408,7 @@ sub setup_netmap() {
|
||||
my $ruleout = '';
|
||||
my $iface = $interface;
|
||||
|
||||
fatal_error "Unknown interface ($interface)" unless my $interfaceref = known_interface( $interface );
|
||||
fatal_error "Unknown interface ($interface)" unless my $interfaceref = known_interface( $interface, 0 );
|
||||
|
||||
unless ( $interfaceref->{root} ) {
|
||||
$rulein = match_source_dev( $interface );
|
||||
|
@ -35,7 +35,7 @@ use strict;
|
||||
our @ISA = qw(Exporter);
|
||||
our @EXPORT = qw( setup_providers @routemarked_interfaces handle_stickiness handle_optional_interfaces );
|
||||
our @EXPORT_OK = qw( initialize lookup_provider );
|
||||
our $VERSION = '4.4_11';
|
||||
our $VERSION = '4.4_13';
|
||||
|
||||
use constant { LOCAL_TABLE => 255,
|
||||
MAIN_TABLE => 254,
|
||||
@ -275,7 +275,7 @@ sub add_a_provider( ) {
|
||||
require_capability 'REALM_MATCH', "Configuring multiple providers through one interface", "s";
|
||||
}
|
||||
|
||||
fatal_error "Unknown Interface ($interface)" unless known_interface $interface;
|
||||
fatal_error "Unknown Interface ($interface)" unless known_interface( $interface, 1 );
|
||||
fatal_error "A bridge port ($interface) may not be configured as a provider interface" if port_to_bridge $interface;
|
||||
|
||||
my $physical = get_physical $interface;
|
||||
@ -846,53 +846,100 @@ sub lookup_provider( $ ) {
|
||||
sub handle_optional_interfaces( $ ) {
|
||||
|
||||
my $returnvalue = verify_required_interfaces( shift );
|
||||
#
|
||||
# find_interfaces_by_option1() does not return wildcard interfaces. If an interface is defined
|
||||
# as a wildcard in /etc/shorewall/interfaces, then only specific interfaces matching that
|
||||
# wildcard are returned.
|
||||
#
|
||||
my $interfaces = find_interfaces_by_option1 'optional';
|
||||
my $require = $config{REQUIRE_INTERFACE};
|
||||
my $wildcards = 0;
|
||||
my $interfaces = find_interfaces_by_option1 'optional', $wildcards;
|
||||
|
||||
if ( $config{REQUIRE_INTERFACE} ) {
|
||||
emit( 'HAVE_INTERFACE=' );
|
||||
emit( '' );
|
||||
}
|
||||
emit( 'HAVE_INTERFACE=', '' ) if $require;
|
||||
|
||||
if ( @$interfaces ) {
|
||||
for my $interface ( @$interfaces ) {
|
||||
my $provider = $provider_interfaces{$interface};
|
||||
my $physical = get_physical $interface;
|
||||
my $base = uc chain_base( $physical );
|
||||
#
|
||||
# Clear the '_IS_USABLE' variables
|
||||
#
|
||||
emit( join( '_', 'SW', uc chain_base( get_physical( $_ ) ) , 'IS_USABLE=' ) ) for @$interfaces;
|
||||
|
||||
emit( '' );
|
||||
if ( $wildcards ) {
|
||||
emit( '',
|
||||
'interfaces=$($IP -' . $family . ' addr list | egrep \'^[[:digit:]]+\' | while read number interface rest; do echo ${interface%:}; done)',
|
||||
'',
|
||||
'for interface in $interfaces; do'
|
||||
);
|
||||
|
||||
if ( $provider ) {
|
||||
#
|
||||
# This interface is associated with a non-shared provider -- get the provider table entry
|
||||
#
|
||||
my $providerref = $providers{$provider};
|
||||
push_indent;
|
||||
|
||||
if ( $providerref->{gatewaycase} eq 'detect' ) {
|
||||
emit qq(if interface_is_usable $physical && [ -n "$providerref->{gateway}" ]; then);
|
||||
} else {
|
||||
emit qq(if interface_is_usable $physical; then);
|
||||
}
|
||||
emit ( 'case "$interface" in'
|
||||
);
|
||||
|
||||
push_indent;
|
||||
} else {
|
||||
emit '';
|
||||
}
|
||||
|
||||
for my $interface ( grep $provider_interfaces{$_}, @$interfaces ) {
|
||||
my $provider = $provider_interfaces{$interface};
|
||||
my $physical = get_physical $interface;
|
||||
my $base = uc chain_base( $physical );
|
||||
my $providerref = $providers{$provider};
|
||||
|
||||
emit( "$physical)" ) if $wildcards;
|
||||
|
||||
push_indent;
|
||||
|
||||
if ( $providerref->{gatewaycase} eq 'detect' ) {
|
||||
emit qq(if interface_is_usable $physical && [ -n "$providerref->{gateway}" ]; then);
|
||||
} else {
|
||||
#
|
||||
# Not a provider interface
|
||||
#
|
||||
emit qq(if interface_is_usable $physical; then);
|
||||
}
|
||||
|
||||
emit( ' HAVE_INTERFACE=Yes' ) if $config{REQUIRE_INTERFACE};
|
||||
emit( ' HAVE_INTERFACE=Yes' ) if $require;
|
||||
|
||||
emit( " SW_${base}_IS_USABLE=Yes" ,
|
||||
'else' ,
|
||||
" SW_${base}_IS_USABLE=" ,
|
||||
'fi' );
|
||||
|
||||
emit( ';;' ), pop_indent if $wildcards;
|
||||
}
|
||||
|
||||
if ( $config{REQUIRE_INTERFACE} ) {
|
||||
for my $interface ( grep ! $provider_interfaces{$_}, @$interfaces ) {
|
||||
my $physical = get_physical $interface;
|
||||
my $base = uc chain_base( $physical );
|
||||
my $case = $physical;
|
||||
my $wild = $case =~ s/\+$/*/;
|
||||
|
||||
if ( $wildcards ) {
|
||||
emit( "$case)" );
|
||||
push_indent;
|
||||
|
||||
|
||||
if ( $wild ) {
|
||||
emit( qq(if [ -z "\$SW_${base}_IS_USABLE" ]; then) );
|
||||
push_indent;
|
||||
emit ( 'if interface_is_usable $interface; then' );
|
||||
} else {
|
||||
emit ( "if interface_is_usable $physical; then" );
|
||||
}
|
||||
} else {
|
||||
emit ( "if interface_is_usable $physical; then" );
|
||||
}
|
||||
|
||||
emit ( ' HAVE_INTERFACE=Yes' ) if $require;
|
||||
|
||||
emit ( " SW_${base}_IS_USABLE=Yes" ,
|
||||
'fi' );
|
||||
|
||||
if ( $wildcards ) {
|
||||
pop_indent, emit( 'fi' ) if $wild;
|
||||
emit( ';;' );
|
||||
pop_indent;
|
||||
}
|
||||
}
|
||||
|
||||
if ( $wildcards ) {
|
||||
emit( 'esac' );
|
||||
pop_indent;
|
||||
emit('done' );
|
||||
}
|
||||
|
||||
if ( $require ) {
|
||||
emit( '',
|
||||
'if [ -z "$HAVE_INTERFACE" ]; then' ,
|
||||
' case "$COMMAND" in',
|
||||
|
@ -177,7 +177,7 @@ sub setup_ecn()
|
||||
|
||||
my ($interface, $hosts ) = split_line 1, 2, 'ecn file entry';
|
||||
|
||||
fatal_error "Unknown interface ($interface)" unless known_interface $interface;
|
||||
fatal_error "Unknown interface ($interface)" unless known_interface( $interface, 0 );
|
||||
|
||||
$interfaces{$interface} = 1;
|
||||
|
||||
@ -328,7 +328,7 @@ sub process_routestopped() {
|
||||
|
||||
my $interfaceref;
|
||||
|
||||
fatal_error "Unknown interface ($interface)" unless $interfaceref = known_interface $interface;
|
||||
fatal_error "Unknown interface ($interface)" unless $interfaceref = known_interface( $interface, 0 );
|
||||
$hosts = ALLIP unless $hosts && $hosts ne '-';
|
||||
|
||||
my $routeback = 0;
|
||||
@ -769,7 +769,7 @@ sub setup_mac_lists( $ ) {
|
||||
my $targetref = $maclist_targets{$disposition};
|
||||
|
||||
fatal_error "Invalid DISPOSITION ($original_disposition)" if ! $targetref || ( ( $table eq 'mangle' ) && ! $targetref->{mangle} );
|
||||
fatal_error "Unknown Interface ($interface)" unless known_interface( $interface );
|
||||
fatal_error "Unknown Interface ($interface)" unless known_interface( $interface, 0 );
|
||||
fatal_error "No hosts on $interface have the maclist option specified" unless $maclist_interfaces{$interface};
|
||||
|
||||
my $chainref = $chain_table{$table}{( $ttl ? macrecent_target $interface : mac_chain $interface )};
|
||||
|
@ -83,7 +83,7 @@ our @EXPORT = qw( NOTHING
|
||||
);
|
||||
|
||||
our @EXPORT_OK = qw( initialize );
|
||||
our $VERSION = '4.4_12';
|
||||
our $VERSION = '4.4_13';
|
||||
|
||||
#
|
||||
# IPSEC Option types
|
||||
@ -1152,11 +1152,12 @@ sub map_physical( $$ ) {
|
||||
#
|
||||
# Returns true if passed interface matches an entry in /etc/shorewall/interfaces
|
||||
#
|
||||
# If the passed name matches a wildcard, an entry for the name is added in %interfaces to speed up validation of other references to that name.
|
||||
# If the passed name matches a wildcard and 'cache' is true, an entry for the name is added in
|
||||
# %interfaces.
|
||||
#
|
||||
sub known_interface($)
|
||||
sub known_interface($$)
|
||||
{
|
||||
my $interface = $_[0];
|
||||
my ( $interface, $cache ) = @_;
|
||||
my $interfaceref = $interfaces{$interface};
|
||||
|
||||
return $interfaceref if $interfaceref;
|
||||
@ -1165,18 +1166,19 @@ sub known_interface($)
|
||||
$interfaceref = $interfaces{$i};
|
||||
my $root = $interfaceref->{root};
|
||||
if ( $i ne $root && substr( $interface, 0, length $root ) eq $root ) {
|
||||
#
|
||||
# Cache this result for future reference. We set the 'name' to the name of the entry that appears in /etc/shorewall/interfaces and we do not set the root;
|
||||
#
|
||||
my $physical = map_physical( $interface, $interfaceref );
|
||||
|
||||
return $interfaces{$interface} = { options => $interfaceref->{options},
|
||||
bridge => $interfaceref->{bridge} ,
|
||||
name => $i ,
|
||||
number => $interfaceref->{number} ,
|
||||
physical => $physical,
|
||||
base => chain_base( $physical ),
|
||||
};
|
||||
my $copyref = { options => $interfaceref->{options},
|
||||
bridge => $interfaceref->{bridge} ,
|
||||
name => $i ,
|
||||
number => $interfaceref->{number} ,
|
||||
physical => $physical ,
|
||||
base => chain_base( $physical ) ,
|
||||
};
|
||||
|
||||
$interfaces{$interface} = $copyref if $cache;
|
||||
|
||||
return $copyref;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1228,7 +1230,7 @@ sub get_physical( $ ) {
|
||||
#
|
||||
sub physical_name( $ ) {
|
||||
my $device = shift;
|
||||
my $devref = known_interface $device;
|
||||
my $devref = known_interface( $device, 0 );
|
||||
|
||||
$devref ? $devref->{physical} : $device;
|
||||
}
|
||||
@ -1287,24 +1289,31 @@ sub find_interfaces_by_option( $ ) {
|
||||
}
|
||||
|
||||
#
|
||||
# Returns reference to array of interfaces with the passed option
|
||||
# Returns reference to array of interfaces with the passed option. Unlike the preceding function, this one:
|
||||
#
|
||||
sub find_interfaces_by_option1( $ ) {
|
||||
my $option = $_[0];
|
||||
# - All entries in %interfaces are searched.
|
||||
# - The second argument is used to return an indication of the presents of wildcard interfaces
|
||||
#
|
||||
sub find_interfaces_by_option1( $\$ ) {
|
||||
my ( $option, $wildref) = @_;
|
||||
my @ints = ();
|
||||
my $wild = 0;
|
||||
|
||||
for my $interface ( keys %interfaces ) {
|
||||
for my $interface ( sort { $interfaces{$a}->{number} <=> $interfaces{$b}->{number} }
|
||||
keys %interfaces ) {
|
||||
my $interfaceref = $interfaces{$interface};
|
||||
|
||||
next unless defined $interfaceref->{physical};
|
||||
next if $interfaceref->{physical} =~ /\+/;
|
||||
|
||||
my $optionsref = $interfaceref->{options};
|
||||
|
||||
if ( $optionsref && defined $optionsref->{$option} ) {
|
||||
$wild ||= ( $interfaceref->{physical} =~ /\+$/ );
|
||||
push @ints , $interface
|
||||
}
|
||||
}
|
||||
|
||||
$$wildref = $wild;
|
||||
\@ints;
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,8 @@ Changes in Shorewall 4.4.13
|
||||
|
||||
4) Fix exclusion with CONTINUE/NONAT/ACCEPT+
|
||||
|
||||
5) Re-implement optional interface handling.
|
||||
|
||||
Changes in Shorewall 4.4.12
|
||||
|
||||
1) Fix IPv6 shorecap program.
|
||||
|
@ -42,6 +42,58 @@ VI. PROBLEMS CORRECTED AND NEW FEATURES IN PRIOR RELEASES
|
||||
who utilize a capabilities file should re-generate the file using
|
||||
this release.
|
||||
|
||||
7) Interface handling has been extensively modified in this release
|
||||
to correct a number of problems with the earlier
|
||||
implementation. Among those problems:
|
||||
|
||||
- Invalid shell variable names could be generated in the firewall
|
||||
script. The generated firewall script uses shell variables to
|
||||
track the availability of optional and required interfaces and
|
||||
to record detected gateways, detected addresses, etc.
|
||||
|
||||
- The same shell variable name could be generated by two different
|
||||
interface names.
|
||||
|
||||
- Entries in the interfaces file with a wildcard physical name
|
||||
(physical name ends with "+") and with the 'optional' option were
|
||||
handled strangely.
|
||||
|
||||
o If there were references to specific interfaces that matched
|
||||
the wildcard, those entries were handled as if they had been
|
||||
defined as optional in the interfaces file.
|
||||
|
||||
o If there were no references matching the wildcard, then the
|
||||
'optional' option was effectively ignored.
|
||||
|
||||
The new implementation:
|
||||
|
||||
- Insures valid shell variable names.
|
||||
|
||||
- Insures that shell variable names are unique.
|
||||
|
||||
- Handles interface names appearing in the INTERFACE column of the
|
||||
providers file as a special case for 'optional'. If the name
|
||||
matches a wildcard entry in the interfaces file then the
|
||||
usability of the specific interface is tracked individually.
|
||||
|
||||
- Handles the availabilty of other interfaces matching a wildcard
|
||||
as a group; if there is one useable interface in the group then
|
||||
the wildcard itself is considered usable.
|
||||
|
||||
The following example illustrates this use case:
|
||||
|
||||
/etc/shorewall/interfaces
|
||||
|
||||
net ppp+ - optional
|
||||
|
||||
/etc/shorewall/shorewall.conf
|
||||
|
||||
REQUIRE_INTERFACE=Yes
|
||||
|
||||
If there is any usable PPP interface then the firewall will be
|
||||
allowed to start. Previously, the firewall would never be allowed
|
||||
to start.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
I I. K N O W N P R O B L E M S R E M A I N I N G
|
||||
----------------------------------------------------------------------------
|
||||
|
Loading…
Reference in New Issue
Block a user