First working version of new Bridge code

git-svn-id: https://shorewall.svn.sourceforge.net/svnroot/shorewall/trunk@6470 fbd18981-670d-0410-9b5c-8dc0c1a9a2bb
This commit is contained in:
teastep 2007-06-06 15:34:47 +00:00
parent 40f3593f69
commit a3961093be
4 changed files with 105 additions and 47 deletions

View File

@ -98,6 +98,8 @@ our @EXPORT = qw( STANDARD
do_ratelimit do_ratelimit
do_user do_user
do_tos do_tos
match_source_dev
match_dest_dev
iprange_match iprange_match
match_source_net match_source_net
match_dest_net match_dest_net
@ -1029,6 +1031,32 @@ sub do_tos( $ ) {
$tos ne '-' ? "-m tos --tos $tos " : ''; $tos ne '-' ? "-m tos --tos $tos " : '';
} }
#
# Match Source Interface
#
sub match_source_dev( $ ) {
my $interface = shift;
my $interfaceref = $interfaces{$interface};
if ( $interfaceref->{options}{port} ) {
"-i $interfaceref->{bridge} -m physdev --physdev-in $interface ";
} else {
"-i $interface ";
}
}
#
# Match Dest device
#
sub match_dest_dev( $ ) {
my $interface = shift;
my $interfaceref = $interfaces{$interface};
if ( $interfaceref->{options}{port} ) {
"-o $interfaceref->{bridge} -m physdev --physdev-out $interface ";
} else {
"-o $interface ";
}
}
# #
# Avoid generating a second '-m iprange' in a single rule. # Avoid generating a second '-m iprange' in a single rule.
# #
@ -1414,6 +1442,8 @@ sub expand_rule( $$$$$$$$$$ )
# #
# An interface in the SOURCE column of a masq file # An interface in the SOURCE column of a masq file
# #
fatal_error "Bridge ports may not appear in the SOURCE column of this file" if port_to_bridge( $iiface );
my $networks = get_interface_nets ( $iiface ); my $networks = get_interface_nets ( $iiface );
add_command( $chainref , join( '', 'for source in ', $networks, '; do' ) ); add_command( $chainref , join( '', 'for source in ', $networks, '; do' ) );
@ -1424,9 +1454,8 @@ sub expand_rule( $$$$$$$$$$ )
# #
$chainref->{loopcount}++; $chainref->{loopcount}++;
} else { } else {
fatal_error "Source Interface ($iiface) not allowed when the source zone is $firewall_zone" fatal_error "Source Interface ($iiface) not allowed when the source zone is $firewall_zone" if $restriction & OUTPUT_RESTRICT;
if $restriction & OUTPUT_RESTRICT; $rule .= match_source_dev( $iiface );
$rule .= "-i $iiface ";
} }
} }
@ -1480,13 +1509,19 @@ sub expand_rule( $$$$$$$$$$ )
# #
# ADDRESS 'detect' in the masq file. # ADDRESS 'detect' in the masq file.
# #
fatal_error "Bridge port ( $diface) not allowed" if port_to_bridge( $diface );
add_command( $chainref , 'for dest in ' . get_interface_addresses( $diface) . '; do' ); add_command( $chainref , 'for dest in ' . get_interface_addresses( $diface) . '; do' );
$rule .= '-d $dest'; $rule .= '-d $dest';
$chainref->{loopcount}++; $chainref->{loopcount}++;
} else { } else {
fatal_error "Destination Interface ($diface) not allowed when the destination zone is $firewall_zone" fatal_error "Destination Interface ($diface) not allowed when the destination zone is $firewall_zone" if $restriction & INPUT_RESTRICT;
if $restriction & INPUT_RESTRICT;
$rule .= "-o $diface "; if ( $iiface ) {
my $bridge = port_to_bridge( $diface );
fatal_error "Source interface ( $iiface) is not a port on the same bridge as the destination interface ( $diface )" if $bridge && $bridge ne source_port_to_bridge( $iiface );
}
$rule .= match_dest_dev( $diface );
} }
} }

View File

@ -38,6 +38,7 @@ our @ISA = qw(Exporter);
our @EXPORT = qw( add_group_to_zone our @EXPORT = qw( add_group_to_zone
validate_interfaces_file validate_interfaces_file
known_interface known_interface
port_to_bridge
interface_is_optional interface_is_optional
find_interfaces_by_option find_interfaces_by_option
get_interface_option get_interface_option
@ -182,13 +183,15 @@ sub validate_interfaces_file()
my $first_entry = 1; my $first_entry = 1;
my @ifaces;
while ( read_a_line ) { while ( read_a_line ) {
if ( $first_entry ) { if ( $first_entry ) {
progress_message2 "$doing $fn..."; progress_message2 "$doing $fn...";
$first_entry = 0; $first_entry = 0;
} }
my ($zone, $interface, $networks, $options ) = split_line 2, 4, 'interfaces file'; my ($zone, $interface, $networks, $options ) = split_line 2, 4, 'interfaces file';
my $zoneref; my $zoneref;
my $bridge = ''; my $bridge = '';
@ -209,23 +212,32 @@ sub validate_interfaces_file()
fatal_error "Invalid INTERFACE" if defined $extra || ! $interface; fatal_error "Invalid INTERFACE" if defined $extra || ! $interface;
fatal_error "Duplicate Interface ($interface)" if $interfaces{$interface}; fatal_error "Invalid Interface Name ( $interface )" if $interface eq '+';
fatal_error "Invalid Interface Name: $interface" if $interface eq '+';
if ( defined $port ) { if ( defined $port ) {
require_capability( 'PHYSDEV_MATCH', 'Bridge Ports', ''); require_capability( 'PHYSDEV_MATCH', 'Bridge Ports', '');
require_capability( 'KLUDGEFREE', 'Bridge Ports', ''); require_capability( 'KLUDGEFREE', 'Bridge Ports', '');
fatal_error "Duplicate Interface ( $port )" if $interfaces{$port};
fatal_error "$interface is not a defined bridge" unless $interfaces{$interface} && $interfaces{$interface}{options}{bridge}; fatal_error "$interface is not a defined bridge" unless $interfaces{$interface} && $interfaces{$interface}{options}{bridge};
fatal_error "Invalid Bridge Port Name ($port)" unless $port =~ /^([\w.@%-]+\+?)$/; fatal_error "Invalid Interface Name ( $interface:$port )" unless $port =~ /^[\w.@%-]+\+?$/;
fatal_error "Bridge Ports may only be associated with 'bport' zones" if $zone && $zoneref->{type} ne 'bport4'; fatal_error "Bridge Ports may only be associated with 'bport' zones" if $zone && $zoneref->{type} ne 'bport4';
if ( $zone ) {
if ( $zoneref->{bridge} ) {
fatal_error "Bridge Port zones may only be associated with a single bridge" if $zoneref->{bridge} ne $interface;
} else {
$zoneref->{bridge} = $interface;
}
}
$interfaces{$port}{bridge} = $bridge = $interface; $interfaces{$port}{bridge} = $bridge = $interface;
$interface = $port; $interface = $port;
} else { } else {
fatal_error "Duplicate Interface ( $interface )" if $interfaces{$interface};
fatal_error "Zones of type 'bport' may only be associated with bridge ports" if $zone && $zoneref->{type} eq 'bport4'; fatal_error "Zones of type 'bport' may only be associated with bridge ports" if $zone && $zoneref->{type} eq 'bport4';
$interfaces{$interface}{bridge} = $interface; $interfaces{$interface}{bridge} = $interface;
} }
my $wildcard = 0; my $wildcard = 0;
if ( $interface =~ /\+$/ ) { if ( $interface =~ /\+$/ ) {
@ -234,7 +246,7 @@ sub validate_interfaces_file()
} else { } else {
$interfaces{$interface}{root} = $interface; $interfaces{$interface}{root} = $interface;
} }
unless ( $networks eq '' || $networks eq 'detect' ) { unless ( $networks eq '' || $networks eq 'detect' ) {
for my $address ( split /,/, $networks ) { for my $address ( split /,/, $networks ) {
@ -300,7 +312,7 @@ sub validate_interfaces_file()
$interfaces{$interface}{options} = $optionsref = \%options; $interfaces{$interface}{options} = $optionsref = \%options;
push @interfaces, $interface; push @ifaces, $interface;
my @networks; my @networks;
@ -316,10 +328,27 @@ sub validate_interfaces_file()
add_group_to_zone( $zone, $zoneref->{type}, $interface, \@networks, $optionsref ) if $zone && @networks; add_group_to_zone( $zone, $zoneref->{type}, $interface, \@networks, $optionsref ) if $zone && @networks;
$interfaces{$interface}{zone} = $zone; #Must follow the call to add_group_to_zone() $interfaces{$interface}{zone} = $zone; #Must follow the call to add_group_to_zone()
progress_message " Interface \"$line\" Validated"; progress_message " Interface \"$line\" Validated";
} }
#
# We now assemble the @interfaces array such that bridge ports immediately precede their associated bridge
#
for my $interface ( @ifaces ) {
my $interfaceref = $interfaces{$interface};
next if $interfaceref->{options}{port};
if ( $interfaceref->{options}{bridge} ) {
for my $port ( grep $interfaces{$_}{options}{port} && $interfaces{$_}{bridge} eq $interface, @ifaces ) {
push @interfaces, $port;
}
}
push @interfaces, $interface;
}
} }
# #
@ -349,6 +378,24 @@ sub known_interface($)
0; 0;
} }
#
# Return the bridge associated with the passed interface. If the interface is not a bridge port,
# return ''
#
sub port_to_bridge( $ ) {
my $portref = $interfaces{$_[0]};
return $portref && $portref->{options}{port} ? $portref->{bridge} : '';
}
#
# Return the bridge associated with the passed interface. If the interface is not a bridge port, return
# the name of the interface itself.
#
sub source_port_to_bridge( $ ) {
my $portref = $interfaces{$_[0]};
return $portref ? $portref->{bridge} : '';
}
# #
# Return the 'optional' setting of the passed interface # Return the 'optional' setting of the passed interface
# #

View File

@ -1374,32 +1374,6 @@ sub generate_matrix() {
add_rule $chainref, "-j $name"; add_rule $chainref, "-j $name";
} }
#
# Match Source Interface
#
sub match_source_dev( $ ) {
my $interface = shift;
my $interfaceref = $interfaces{$interface};
if ( $interfaceref->{options}{port} ) {
"-i $interfaceref->{bridge} -m physdev --physdev-in $interface ";
} else {
"-i $interface ";
}
}
#
# Match Dest device
#
sub match_dest_dev( $ ) {
my $interface = shift;
my $interfaceref = $interfaces{$interface};
if ( $interfaceref->{options}{port} ) {
"-o $interfaceref->{bridge} -m physdev --physdev-out $interface ";
} else {
"-o $interface ";
}
}
# #
# Insert the passed exclusions at the front of the passed chain. # Insert the passed exclusions at the front of the passed chain.
# #
@ -1611,6 +1585,10 @@ sub generate_matrix() {
next if ( %{ $zoneref->{interfaces} } < 2 ) && ! ( $zoneref->{options}{in_out}{routeback} || @$exclusions ); next if ( %{ $zoneref->{interfaces} } < 2 ) && ! ( $zoneref->{options}{in_out}{routeback} || @$exclusions );
} }
if ( $zone1ref->{type} eq 'bport4' ) {
next unless $zoneref->{bridge} eq $zone1ref->{bridge};
}
if ( $chain =~ /2all$/ ) { if ( $chain =~ /2all$/ ) {
if ( $chain ne $last_chain ) { if ( $chain ne $last_chain ) {
$last_chain = $chain; $last_chain = $chain;
@ -1665,6 +1643,10 @@ sub generate_matrix() {
next ZONE1 if ( $num_ifaces = %{$zoneref->{interfaces}} ) < 2 && ! ( $zoneref->{options}{in_out}{routeback} || @$exclusions ); next ZONE1 if ( $num_ifaces = %{$zoneref->{interfaces}} ) < 2 && ! ( $zoneref->{options}{in_out}{routeback} || @$exclusions );
} }
if ( $zone1ref->{type} eq 'bport4' ) {
next ZONE1 unless $zoneref->{bridge} eq $zone1ref->{bridge};
}
my $chainref = $filter_table->{$chain}; my $chainref = $filter_table->{$chain};
my $exclusions1 = $zone1ref->{exclusions}; my $exclusions1 = $zone1ref->{exclusions};

View File

@ -234,12 +234,6 @@ sub determine_zones()
$zoneref->{type} = 'ipsec4'; $zoneref->{type} = 'ipsec4';
} elsif ( $type =~ /^bport4?$/i ) { } elsif ( $type =~ /^bport4?$/i ) {
fatal_error "Bridge Port zones must have a single parent zone" unless @parents == 1; fatal_error "Bridge Port zones must have a single parent zone" unless @parents == 1;
for my $p ( @parents ) {
my $interfaceref = $interfaces{$1};
fatal_error "Parent Zone $p is not associated with device $1" unless $interfaceref && $interfaceref->{zone} eq $zone;
}
$zoneref->{type} = 'bport4'; $zoneref->{type} = 'bport4';
} elsif ( $type eq 'firewall' ) { } elsif ( $type eq 'firewall' ) {