Split add_input_jumps() into two functions

- Added add_forward_jump()
- Added lots of comments

Signed-off-by: Tom Eastep <teastep@shorewall.net>
This commit is contained in:
Tom Eastep 2012-06-09 17:21:59 -07:00
parent 00f7b9d0dd
commit 1f54d19981

View File

@ -1316,9 +1316,15 @@ sub handle_loopback_traffic() {
my @rule;
if ( @zones > 1 ) {
#
# We have a vserver zone -- route output through a separate chain
#
$outchainref = new_standard_chain 'loopback';
add_ijump $filter_table->{OUTPUT}, j => $outchainref, o => 'lo';
} else {
#
# Only the firewall -- just use the OUTPUT chain
#
$outchainref = $filter_table->{OUTPUT};
@rule = ( o => 'lo');
}
@ -1327,7 +1333,9 @@ sub handle_loopback_traffic() {
my $z1ref = find_zone( $z1 );
my $type1 = $z1ref->{type};
my $natref = $nat_table->{dnat_chain $z1};
#
# Add jumps in the 'output' chain to the rules chains
#
if ( $type1 == FIREWALL ) {
for my $z2 ( @zones ) {
my $chain = rules_target( $z1, $z2 );
@ -1341,6 +1349,9 @@ sub handle_loopback_traffic() {
}
if ( $natref && $natref->{referenced} ) {
#
# There are DNAT rules with this zone as the source -- add jumps from the nat OUTPUT chain
#
my $source_hosts_ref = defined_zone( $z1 )->{hosts};
for my $typeref ( values %{$source_hosts_ref} ) {
@ -1479,25 +1490,40 @@ sub handle_complex_zone( $$ ) {
my $interfaceref = find_interface $interface;
if ( use_forward_chain( $interface, $sourcechainref ) ) {
#
# Use the interface forward chain
#
if ( $interfaceref->{ports} && $interfaceref->{options}{bridge} ) {
#
# This is a bridge with ports
#
@interfacematch = imatch_source_dev $interface;
#
# Copy the rules from the interface forward chain to the zone forward chain unless they have already been copied
#
copy_rules( $sourcechainref, $frwd_ref, 1 ) unless $ipsec_jump_added{$zone}++;
#
# Jump directly from FORWARD to the zone forward chain
#
$sourcechainref = $filter_table->{FORWARD};
} elsif ( $interfaceref->{options}{port} ) {
#
# The forwarding chain for a bridge with ports is always used
# The forwarding chain for a bridge with ports is always used -- use physdev match for this interface
#
add_ijump( $filter_table->{ forward_chain $interfaceref->{bridge} } ,
j => $sourcechainref ,
imatch_source_dev( $interface , 1 ) )
unless $forward_jump_added{$interface}++;
} else {
#
# Add jump from FORWARD to the intrface forward chain
#
add_ijump $filter_table->{FORWARD} , j => $sourcechainref, imatch_source_dev( $interface ) unless $forward_jump_added{$interface}++;
}
} else {
if ( $interfaceref->{options}{port} ) {
#
# The forwarding chain for a bridge with ports is always used
# The forwarding chain for a bridge with ports is always used -- use physdev match
#
$sourcechainref = $filter_table->{ forward_chain $interfaceref->{bridge} };
@interfacematch = imatch_source_dev $interface, 1;
@ -1505,12 +1531,16 @@ sub handle_complex_zone( $$ ) {
$sourcechainref = $filter_table->{FORWARD};
@interfacematch = imatch_source_dev $interface;
}
#
# copy any rules from the interface forward chain to the zone forward chain
#
move_rules( $filter_table->{forward_chain $interface} , $frwd_ref );
}
my $arrayref = $source_ref->{$interface};
#
# Now add the jumps from the source chain (interface forward or FORWARD) to the zone forward chain
#
for my $hostref ( @{$arrayref} ) {
my @ipsec_match = match_ipsec_in $zone , $hostref;
for my $net ( @{$hostref->{hosts}} ) {
@ -1573,7 +1603,7 @@ sub handle_nested_zone( $$ ) {
}
#
# Add output jumps to the passed zone:interface:hostref:net
# Add output jump to the passed zone:interface:hostref:net
#
sub add_output_jumps( $$$$$$$ ) {
my ( $zone, $interface, $hostref, $net, $exclusions, $isport, $bridge, ) = @_;
@ -1592,37 +1622,65 @@ sub add_output_jumps( $$$$$$$ ) {
my @ipsec_out_match = match_ipsec_out $zone , $hostref;
if ( @vservers || use_output_chain( $interface, $interfacechainref ) || ( @{$interfacechainref->{rules}} && ! $chain1ref ) ) {
#
# - There are vserver zones (so OUTPUT will have multiple source; or
# - We must use the interface output chain; or
# - There are rules in the interface chain and none in the rules chain
#
# In any of these cases use the inteface output chain
#
$outputref = $interfacechainref;
if ( $isport ) {
#
# It is a bridge port zone -- use the bridges output chain and match the physdev
#
add_ijump( $filter_table->{ output_chain $bridge },
j => $outputref ,
imatch_dest_dev( $interface, 1 ) )
unless $output_jump_added{$interface}++;
} else {
#
# Not a bridge -- match the input interface
#
add_ijump $filter_table->{OUTPUT}, j => $outputref, imatch_dest_dev( $interface ) unless $output_jump_added{$interface}++;
}
$use_output = 1;
unless ( lc $net eq IPv6_LINKLOCAL ) {
#
# Generate output rules for the vservers
#
for my $vzone ( @vservers ) {
generate_source_rules ( $outputref, $vzone, $zone, @dest );
}
}
} elsif ( $isport ) {
#
# It is a bridge port zone -- use the bridges output chain and match the physdev
#
$outputref = $filter_table->{ output_chain $bridge };
@interfacematch = imatch_dest_dev $interface, 1;
} else {
#
# Just put the jump in the OUTPUT chain
#
$outputref = $filter_table->{OUTPUT};
@interfacematch = imatch_dest_dev $interface;
}
#
# Add the jump
#
add_ijump $outputref , j => $nextchain, @interfacematch, @dest, @ipsec_out_match;
#
# Add jump for broadcast
#
add_ijump( $outputref , j => $nextchain, @interfacematch, d => '255.255.255.255' , @ipsec_out_match )
if $family == F_IPV4 && $hostref->{options}{broadcast};
#
# Move the rules from the interface output chain if we didn't use it
#
move_rules( $interfacechainref , $chain1ref ) unless $use_output;
}
@ -1671,14 +1729,13 @@ sub add_prerouting_jumps( $$$$$$$$ ) {
}
#
# Add input jumps from the passed zone:interface:hostref:net
# Add input jump from the passed zone:interface:hostref:net
#
sub add_input_jumps( $$$$$$$$ ) {
my ( $zone, $interface, $hostref, $net, $exclusions, $frwd_ref, $isport, $bridge ) = @_;
our @vservers;
our %input_jump_added;
our %forward_jump_added;
my $chain2 = rules_target $zone, firewall_zone;
my $chain2ref = $filter_table->{$chain2};
@ -1690,72 +1747,128 @@ sub add_input_jumps( $$$$$$$$ ) {
my @ipsec_in_match = match_ipsec_in $zone , $hostref;
if ( @vservers || use_input_chain( $interface, $interfacechainref ) || ! $chain2 || ( @{$interfacechainref->{rules}} && ! $chain2ref ) ) {
#
# - There are vserver zones (so INPUT will have multiple destinations; or
# - We must use the interface input chain; or
# - The zone->firewall policy is CONTINUE; or
# - There are rules in the interface chain and none in the rules chain
#
# In any of these cases use the inteface input chain
#
$inputchainref = $interfacechainref;
if ( $isport ) {
#
# It is a bridge port zone -- use the bridges input chain and match the physdev
#
add_ijump( $filter_table->{ input_chain $bridge },
j => $inputchainref ,
imatch_source_dev($interface, 1) )
unless $input_jump_added{$interface}++;
} else {
#
# Not a bridge -- match the input interface
#
add_ijump $filter_table->{INPUT}, j => $inputchainref, imatch_source_dev($interface) unless $input_jump_added{$interface}++;
}
$use_input = 1;
unless ( lc $net eq IPv6_LINKLOCAL ) {
#
# Generate input rules for the vservers
#
for my $vzone ( @vservers ) {
my $target = rules_target( $zone, $vzone );
generate_dest_rules( $inputchainref, $target, $vzone, @source, @ipsec_in_match ) if $target;
}
}
} elsif ( $isport ) {
#
# It is a bridge port zone -- use the bridges input chain and match the physdev
#
$inputchainref = $filter_table->{ input_chain $bridge };
@interfacematch = imatch_source_dev $interface, 1;
} else {
#
# Just put the jump in the INPUT chain
#
$inputchainref = $filter_table->{INPUT};
@interfacematch = imatch_source_dev $interface;
}
if ( $chain2 ) {
#
# Add the jump from the input chain to the rules chain
#
add_ijump $inputchainref, j => source_exclusion( $exclusions, $chain2 ), @interfacematch, @source, @ipsec_in_match;
move_rules( $interfacechainref , $chain2ref ) unless $use_input;
}
}
if ( $frwd_ref && $hostref->{ipsec} ne 'ipsec' ) {
my $ref = source_exclusion( $exclusions, $frwd_ref );
my $forwardref = $filter_table->{forward_chain $interface};
#
# This function is called when there is forwarding and this net isn't IPSEC protected. It adds the jump for this net to the zone forwarding chain.
#
sub add_forward_jump( $$$$$$$$ ) {
my ( $zone, $interface, $hostref, $net, $exclusions, $frwd_ref, $isport, $bridge ) = @_;
if ( use_forward_chain $interface, $forwardref ) {
add_ijump $forwardref , j => $ref, @source, @ipsec_in_match;
our %forward_jump_added;
if ( $isport ) {
add_ijump( $filter_table->{ forward_chain $bridge } ,
j => $forwardref ,
imatch_source_dev( $interface , 1 ) )
unless $forward_jump_added{$interface}++;
} else {
add_ijump $filter_table->{FORWARD} , j => $forwardref, imatch_source_dev( $interface ) unless $forward_jump_added{$interface}++;
}
my @source = imatch_source_net $net;
my @ipsec_in_match = match_ipsec_in $zone , $hostref;
my $ref = source_exclusion( $exclusions, $frwd_ref );
my $forwardref = $filter_table->{forward_chain $interface};
if ( use_forward_chain $interface, $forwardref ) {
#
# We must use the interface forwarding chain -- add the jump from the interface forward chain to the zone forward chain.
#
add_ijump $forwardref , j => $ref, @source, @ipsec_in_match;
if ( $isport ) {
#
# It is a bridge port zone -- use the bridges input chain and match the physdev
#
add_ijump( $filter_table->{ forward_chain $bridge } ,
j => $forwardref ,
imatch_source_dev( $interface , 1 ) )
unless $forward_jump_added{$interface}++;
} else {
if ( $isport ) {
add_ijump( $filter_table->{ forward_chain $bridge } ,
j => $ref ,
imatch_source_dev( $interface, 1 ) ,
@source,
@ipsec_in_match );
} else {
add_ijump $filter_table->{FORWARD} , j => $ref, imatch_source_dev( $interface ) , @source, @ipsec_in_match;
}
move_rules ( $forwardref , $frwd_ref );
#
# Not a bridge -- match the input interface
#
add_ijump $filter_table->{FORWARD} , j => $forwardref, imatch_source_dev( $interface ) unless $forward_jump_added{$interface}++;
}
} else {
if ( $isport ) {
#
# It is a bridge port zone -- use the bridges input chain and match the physdev
#
add_ijump( $filter_table->{ forward_chain $bridge } ,
j => $ref ,
imatch_source_dev( $interface, 1 ) ,
@source,
@ipsec_in_match );
} else {
#
# Not a bridge -- match the input interface
#
add_ijump $filter_table->{FORWARD} , j => $ref, imatch_source_dev( $interface ) , @source, @ipsec_in_match;
}
move_rules ( $forwardref , $frwd_ref );
}
}
#
# Generate the list of destination zones from the passed source zone when optimization level 1 is selected
#
# - Drop zones where the policy to that zone is 'NONE'
# - Drop this zone if it has only one interface without 'routeback'
# - Drop BPORT zones that are not on the same bridge
# - Eliminate duplicate zones that have the same '2all' (-all) rules chain.
#
sub optimize1_zones( $$@ ) {
my $zone = shift;
my $zoneref = shift;
@ -1766,7 +1879,7 @@ sub optimize1_zones( $$@ ) {
for my $zone1 ( @_ ) {
my $zone1ref = find_zone( $zone1 );
my $policy = $filter_table->{rules_chain( ${zone}, ${zone1} )}->{policy};
next if $policy eq 'NONE';
my $chain = rules_target $zone, $zone1;
@ -1911,6 +2024,10 @@ sub generate_matrix() {
# INPUT
#
add_input_jumps( $zone, $interface, $hostref, $net, $exclusions, $frwd_ref, $isport, $bridge );
#
# FORWARDING Jump for non-IPSEC host group
#
add_forward_jump( $zone, $interface, $hostref, $net, $exclusions, $frwd_ref, $isport, $bridge ) if $frwd_ref && $hostref->{ipsec} ne 'ipsec';
}
} # Subnet Loop
} # Hostref Loop