From fe09646bed3dc9ab71de87b8fd18b601a8f1e7f2 Mon Sep 17 00:00:00 2001 From: Tom Eastep Date: Thu, 17 Nov 2011 09:23:39 -0800 Subject: [PATCH] Make zone types a power of 2. Signed-off-by: Tom Eastep --- Shorewall/Perl/Shorewall/Chains.pm | 4 +- Shorewall/Perl/Shorewall/Misc.pm | 8 +-- Shorewall/Perl/Shorewall/Rules.pm | 14 ++-- Shorewall/Perl/Shorewall/Tunnels.pm | 2 +- Shorewall/Perl/Shorewall/Zones.pm | 105 ++++++++++++---------------- 5 files changed, 59 insertions(+), 74 deletions(-) diff --git a/Shorewall/Perl/Shorewall/Chains.pm b/Shorewall/Perl/Shorewall/Chains.pm index 8a7f86373..ff2913d00 100644 --- a/Shorewall/Perl/Shorewall/Chains.pm +++ b/Shorewall/Perl/Shorewall/Chains.pm @@ -4257,7 +4257,7 @@ sub match_ipsec_in( $$ ) { unless ( $optionsref->{super} || $zoneref->{type} == VSERVER ) { my $match = '--dir in --pol '; - if ( $zoneref->{type} == IPSEC ) { + if ( $zoneref->{type} & IPSEC ) { $match .= "ipsec $optionsref->{in_out}{ipsec}$optionsref->{in}{ipsec}"; } elsif ( have_ipsec ) { $match .= "$hostref->{ipsec} $optionsref->{in_out}{ipsec}$optionsref->{in}{ipsec}"; @@ -4280,7 +4280,7 @@ sub match_ipsec_out( $$ ) { unless ( $optionsref->{super} || $zoneref->{type} == VSERVER ) { my $match = '--dir out --pol '; - if ( $zoneref->{type} == IPSEC ) { + if ( $zoneref->{type} & IPSEC ) { $match .= "ipsec $optionsref->{in_out}{ipsec}$optionsref->{out}{ipsec}"; } elsif ( have_ipsec ) { $match .= "$hostref->{ipsec} $optionsref->{in_out}{ipsec}$optionsref->{out}{ipsec}" diff --git a/Shorewall/Perl/Shorewall/Misc.pm b/Shorewall/Perl/Shorewall/Misc.pm index a727621b6..48ebe6b97 100644 --- a/Shorewall/Perl/Shorewall/Misc.pm +++ b/Shorewall/Perl/Shorewall/Misc.pm @@ -1300,7 +1300,7 @@ sub generate_dest_rules( $$$;@ ) { my $z2ref = find_zone( $z2 ); my $type2 = $z2ref->{type}; - if ( $type2 == VSERVER ) { + if ( $type2 & VSERVER ) { for my $hostref ( @{$z2ref->{hosts}{ip}{'%vserver%'}} ) { my $exclusion = dest_exclusion( $hostref->{exclusions}, $chain); @@ -1707,7 +1707,7 @@ sub generate_matrix() { for my $net ( @{$hostref->{hosts}} ) { my @dest = imatch_dest_net $net; - if ( $chain1 && zone_type ( $zone) != BPORT ) { + if ( $chain1 && ! ( zone_type( $zone) & BPORT ) ) { my $chain1ref = $filter_table->{$chain1}; my $nextchain = dest_exclusion( $exclusions, $chain1 ); my $outputref; @@ -1891,7 +1891,7 @@ sub generate_matrix() { next if ( scalar ( keys( %{ $zoneref->{interfaces}} ) ) < 2 ) && ! $zoneref->{options}{in_out}{routeback}; } - if ( $zone1ref->{type} == BPORT ) { + if ( $zone1ref->{type} & BPORT ) { next unless $zoneref->{bridge} eq $zone1ref->{bridge}; } @@ -1941,7 +1941,7 @@ sub generate_matrix() { next if ( $num_ifaces = scalar( keys ( %{$zoneref->{interfaces}} ) ) ) < 2 && ! $zoneref->{options}{in_out}{routeback}; } - if ( $zone1ref->{type} == BPORT ) { + if ( $zone1ref->{type} & BPORT ) { next unless $zoneref->{bridge} eq $zone1ref->{bridge}; } diff --git a/Shorewall/Perl/Shorewall/Rules.pm b/Shorewall/Perl/Shorewall/Rules.pm index c90b29ef8..fd26389db 100644 --- a/Shorewall/Perl/Shorewall/Rules.pm +++ b/Shorewall/Perl/Shorewall/Rules.pm @@ -379,7 +379,7 @@ sub process_a_policy() { } unless ( $clientwild || $serverwild ) { - if ( zone_type( $server ) == BPORT ) { + if ( zone_type( $server ) & BPORT ) { fatal_error "Invalid policy - DEST zone is a Bridge Port zone but the SOURCE zone is not associated with the same bridge" unless find_zone( $client )->{bridge} eq find_zone( $server)->{bridge} || single_interface( $client ) eq find_zone( $server )->{bridge}; } @@ -515,11 +515,11 @@ sub process_policies() for $zone ( all_zones ) { push @policy_chains, ( new_policy_chain $zone, $zone, 'ACCEPT', PROVISIONAL, 0 ); - push @policy_chains, ( new_policy_chain firewall_zone, $zone, 'NONE', PROVISIONAL, 0 ) if zone_type( $zone ) == BPORT; + push @policy_chains, ( new_policy_chain firewall_zone, $zone, 'NONE', PROVISIONAL, 0 ) if zone_type( $zone ) & BPORT; my $zoneref = find_zone( $zone ); - if ( $config{IMPLICIT_CONTINUE} && ( @{$zoneref->{parents}} || $zoneref->{type} == VSERVER ) ) { + if ( $config{IMPLICIT_CONTINUE} && ( @{$zoneref->{parents}} || $zoneref->{type} & VSERVER ) ) { for my $zone1 ( all_zones ) { unless( $zone eq $zone1 ) { add_or_modify_policy_chain( $zone, $zone1, 0 ); @@ -1889,10 +1889,10 @@ sub process_rule1 ( $$$$$$$$$$$$$$$$ $) { my $restriction = NO_RESTRICT; unless ( $inaction ) { - if ( $sourceref && ( $sourceref->{type} == FIREWALL || $sourceref->{type} == VSERVER ) ) { - $restriction = $destref && ( $destref->{type} == FIREWALL || $destref->{type} == VSERVER ) ? ALL_RESTRICT : OUTPUT_RESTRICT; + if ( $sourceref && ( $sourceref->{type} & ( FIREWALL | VSERVER ) ) ) { + $restriction = $destref && ( $destref->{type} & ( FIREWALL | VSERVER ) ) ? ALL_RESTRICT : OUTPUT_RESTRICT; } else { - $restriction = INPUT_RESTRICT if $destref && ( $destref->{type} == FIREWALL || $destref->{type} == VSERVER ); + $restriction = INPUT_RESTRICT if $destref && ( $destref->{type} & ( FIREWALL | VSERVER ) ); } } @@ -1916,7 +1916,7 @@ sub process_rule1 ( $$$$$$$$$$$$$$$$ $) { # # Check for illegal bridge port rule # - if ( $destref->{type} == BPORT ) { + if ( $destref->{type} & BPORT ) { unless ( $sourceref->{bridge} eq $destref->{bridge} || single_interface( $sourcezone ) eq $destref->{bridge} ) { return 0 if $wildcard; fatal_error "Rules with a DESTINATION Bridge Port zone must have a SOURCE zone on the same bridge"; diff --git a/Shorewall/Perl/Shorewall/Tunnels.pm b/Shorewall/Perl/Shorewall/Tunnels.pm index 6139d5474..affcefc0c 100644 --- a/Shorewall/Perl/Shorewall/Tunnels.pm +++ b/Shorewall/Perl/Shorewall/Tunnels.pm @@ -238,7 +238,7 @@ sub setup_tunnels() { my $zonetype = zone_type( $zone ); - fatal_error "Invalid tunnel ZONE ($zone)" if $zonetype == FIREWALL || $zonetype == BPORT; + fatal_error "Invalid tunnel ZONE ($zone)" if $zonetype & ( FIREWALL | BPORT ); my $inchainref = ensure_rules_chain( rules_chain( ${zone}, ${fw} ) ); my $outchainref = ensure_rules_chain( rules_chain( ${fw}, ${zone} ) ); diff --git a/Shorewall/Perl/Shorewall/Zones.pm b/Shorewall/Perl/Shorewall/Zones.pm index 83aa93ec7..a14cee4c2 100644 --- a/Shorewall/Perl/Shorewall/Zones.pm +++ b/Shorewall/Perl/Shorewall/Zones.pm @@ -132,6 +132,7 @@ use constant { NOTHING => 'NOTHING', # my @zones; my %zones; +my %zonetypes; my $firewall_zone; my %reservedName = ( all => 1, @@ -184,9 +185,9 @@ my $minroot; use constant { FIREWALL => 1, IP => 2, - BPORT => 3, - IPSEC => 4, - VSERVER => 5 }; + BPORT => 4, + IPSEC => 8, + VSERVER => 16 }; use constant { SIMPLE_IF_OPTION => 1, BINARY_IF_OPTION => 2, @@ -276,6 +277,7 @@ sub initialize( $$ ) { destonly => 1, sourceonly => 1, ); + %zonetypes = ( 1 => 'firewall', 2 => 'ipv4', 4 => 'bport4', 8 => 'ipsec4', 16 => 'vserver' ); } else { %validinterfaceoptions = ( blacklist => SIMPLE_IF_OPTION + IF_OPTION_HOST, bridge => SIMPLE_IF_OPTION, @@ -301,6 +303,7 @@ sub initialize( $$ ) { routeback => 1, tcpflags => 1, ); + %zonetypes = ( 1 => 'firewall', 2 => 'ipv6', 4 => 'bport6', 8 => 'ipsec4', 16 => 'vserver' ); } } @@ -363,11 +366,11 @@ sub parse_zone_option_list($$\$) my $key = $key{$e}; if ( $key ) { - fatal_error "Option '$e' not permitted with this zone type " if $key & NOFW && ($zonetype == FIREWALL || $zonetype == VSERVER); + fatal_error "Option '$e' not permitted with this zone type " if $key & NOFW && ($zonetype & ( FIREWALL | VSERVER) ); $$complexref = 1 if $key & COMPLEX; $h{$e} = $val || 1; } else { - fatal_error "The \"$e\" option may only be specified for ipsec zones" unless $zonetype == IPSEC; + fatal_error "The \"$e\" option may only be specified for ipsec zones" unless $zonetype & IPSEC; $options .= $invert; $options .= "--$e "; $options .= "$val "if defined $val; @@ -411,14 +414,6 @@ sub process_zone( \$ ) { if ( $zone =~ /(\w+):([\w,]+)/ ) { $zone = $1; @parents = split_list $2, 'zone'; - - for my $p ( @parents ) { - fatal_error "Invalid Parent List ($2)" unless $p; - fatal_error "Unknown parent zone ($p)" unless $zones{$p}; - fatal_error 'Subzones of firewall zone not allowed' if $zones{$p}{type} == FIREWALL; - fatal_error 'Subzones of a Vserver zone not allowed' if $zones{$p}{type} == VSERVER; - push @{$zones{$p}{children}}, $zone; - } } fatal_error "Invalid zone name ($zone)" unless $zone =~ /^[a-z]\w*$/i && length $zone <= $globals{MAXZONENAMELENGTH}; @@ -431,6 +426,7 @@ sub process_zone( \$ ) { $$ip = 1; } elsif ( $type =~ /^ipsec([46])?$/i ) { fatal_error "Invalid zone type ($type)" if $1 && $1 != $family; + require_capability 'POLICY_MATCH' , 'IPSEC zones', ''; $type = IPSEC; } elsif ( $type =~ /^bport([46])?$/i ) { fatal_error "Invalid zone type ($type)" if $1 && $1 != $family; @@ -453,11 +449,18 @@ sub process_zone( \$ ) { fatal_error "Invalid zone type ($type)"; } - if ( $type eq IPSEC ) { - require_capability 'POLICY_MATCH' , 'IPSEC zones', ''; - for ( @parents ) { - set_super( $zones{$_} ) unless $zones{$_}{type} == IPSEC; - } + for my $p ( @parents ) { + fatal_error "Invalid Parent List ($2)" unless $p; + fatal_error "Unknown parent zone ($p)" unless $zones{$p}; + + my $ptype = $zones{$p}{type}; + + fatal_error 'Subzones of a Vserver zone not allowed' if $ptype & VSERVER; + fatal_error 'Subzones of firewall zone not allowed' if $ptype & FIREWALL; + + set_super( $zones{$p} ) if $type & IPSEC && ! ( $ptype & IPSEC ); + + push @{$zones{$p}{children}}, $zone; } my $complex = 0; @@ -468,7 +471,7 @@ sub process_zone( \$ ) { options => { in_out => parse_zone_option_list( $options , $type, $complex ) , in => parse_zone_option_list( $in_options , $type , $complex ) , out => parse_zone_option_list( $out_options , $type , $complex ) , - complex => ( $type == IPSEC || $complex ) , + complex => ( $type & IPSEC || $complex ) , nested => @parents > 0 , super => 0 , } , @@ -536,7 +539,7 @@ sub determine_zones() # sub haveipseczones() { for my $zoneref ( values %zones ) { - return 1 if $zoneref->{type} == IPSEC; + return 1 if $zoneref->{type} & IPSEC; } 0; @@ -549,22 +552,13 @@ sub zone_report() { progress_message2 "Determining Hosts in Zones..."; - my @translate; - - if ( $family == F_IPV4 ) { - @translate = ( undef, 'firewall', 'ipv4', 'bport4', 'ipsec4', 'vserver' ); - } else { - @translate = ( undef, 'firewall', 'ipv6', 'bport6', 'ipsec6', 'vserver' ); - } - - for my $zone ( @zones ) - { + for my $zone ( @zones ) { my $zoneref = $zones{$zone}; my $hostref = $zoneref->{hosts}; my $type = $zoneref->{type}; my $optionref = $zoneref->{options}; - progress_message_nocompress " $zone ($translate[$type])"; + progress_message_nocompress " $zone ($zonetypes{$type})"; my $printed = 0; @@ -596,7 +590,7 @@ sub zone_report() } unless ( $printed ) { - fatal_error "No bridge has been associated with zone $zone" if $type == BPORT && ! $zoneref->{bridge}; + fatal_error "No bridge has been associated with zone $zone" if $type & BPORT && ! $zoneref->{bridge}; warning_message "*** $zone is an EMPTY ZONE ***" unless $type == FIREWALL; } @@ -606,16 +600,7 @@ sub zone_report() # # This function is called to create the contents of the ${VARDIR}/zones file # -sub dump_zone_contents() -{ - my @xlate; - - if ( $family == F_IPV4 ) { - @xlate = ( undef, 'firewall', 'ipv4', 'bport4', 'ipsec4', 'vserver' ); - } else { - @xlate = ( undef, 'firewall', 'ipv6', 'bport6', 'ipsec6', 'vserver' ); - } - +sub dump_zone_contents() { for my $zone ( @zones ) { my $zoneref = $zones{$zone}; @@ -623,9 +608,9 @@ sub dump_zone_contents() my $type = $zoneref->{type}; my $optionref = $zoneref->{options}; - my $entry = "$zone $xlate[$type]"; + my $entry = "$zone $zonetypes{$type}"; - $entry .= ":$zoneref->{bridge}" if $type == BPORT; + $entry .= ":$zoneref->{bridge}" if $type & BPORT; if ( $hostref ) { for my $type ( sort keys %$hostref ) { @@ -736,7 +721,7 @@ sub add_group_to_zone($$$$$) $zoneref->{options}{in_out}{routeback} = 1 if $options->{routeback}; - my $gtype = $type == IPSEC ? 'ipsec' : 'ip'; + my $gtype = $type & IPSEC ? 'ipsec' : 'ip'; $hostsref = ( $zoneref->{hosts} || ( $zoneref->{hosts} = {} ) ); $typeref = ( $hostsref->{$gtype} || ( $hostsref->{$gtype} = {} ) ); @@ -748,7 +733,7 @@ sub add_group_to_zone($$$$$) push @{$interfaceref}, { options => $options, hosts => \@newnetworks, - ipsec => $type == IPSEC ? 'ipsec' : 'none' , + ipsec => $type & IPSEC ? 'ipsec' : 'none' , exclusions => \@exclusions }; $interfaces{$interface}{options}{routeback} ||= ( $type != IPSEC && $options->{routeback} ); @@ -785,11 +770,11 @@ sub all_zones() { } sub off_firewall_zones() { - grep ( ! ( $zones{$_}{type} == FIREWALL || $zones{$_}{type} == VSERVER ) , @zones ); + grep ( ! ( $zones{$_}{type} & ( FIREWALL | VSERVER ) ) , @zones ); } sub non_firewall_zones() { - grep ( $zones{$_}{type} != FIREWALL , @zones ); + grep ( ! ( $zones{$_}{type} & FIREWALL ) , @zones ); } sub all_parent_zones() { @@ -805,7 +790,7 @@ sub complex_zones() { } sub vserver_zones() { - grep ( $zones{$_}{type} == VSERVER, @zones ); + grep ( $zones{$_}{type} & VSERVER, @zones ); } sub firewall_zone() { @@ -904,7 +889,7 @@ sub process_interface( $$ ) { fatal_error "$interface is not a defined bridge" unless $interfaces{$interface} && $interfaces{$interface}{options}{bridge}; $interfaces{$interface}{ports}++; - fatal_error "Bridge Ports may only be associated with 'bport' zones" if $zone && $zoneref->{type} != BPORT; + fatal_error "Bridge Ports may only be associated with 'bport' zones" if $zone && ! ( $zoneref->{type} & BPORT ); if ( $zone ) { if ( $zoneref->{bridge} ) { @@ -913,15 +898,15 @@ sub process_interface( $$ ) { $zoneref->{bridge} = $interface; } - fatal_error "Vserver zones may not be associated with bridge ports" if $zoneref->{type} == VSERVER; + fatal_error "Vserver zones may not be associated with bridge ports" if $zoneref->{type} & VSERVER; } $bridge = $interface; $interface = $port; } 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} == BPORT; - fatal_error "Vserver zones may not be associated with interfaces" if $zone && $zoneref->{type} == VSERVER; + fatal_error "Zones of type 'bport' may only be associated with bridge ports" if $zone && $zoneref->{type} & BPORT; + fatal_error "Vserver zones may not be associated with interfaces" if $zone && $zoneref->{type} & VSERVER; $bridge = $interface; } @@ -987,7 +972,7 @@ sub process_interface( $$ ) { fatal_error "Invalid Interface option ($option)" unless my $type = $validinterfaceoptions{$option}; if ( $zone ) { - fatal_error qq(The "$option" option may not be specified for a Vserver zone") if $zoneref->{type} == VSERVER && ! ( $type & IF_OPTION_VSERVER ); + fatal_error qq(The "$option" option may not be specified for a Vserver zone") if $zoneref->{type} & VSERVER && ! ( $type & IF_OPTION_VSERVER ); } else { fatal_error "The \"$option\" option may not be specified on a multi-zone interface" if $type & IF_OPTION_ZONEONLY; } @@ -1781,7 +1766,7 @@ sub process_host( ) { fatal_error "Invalid ipset name ($hosts)" unless $hosts =~ /^!?\+[a-zA-Z][-\w]*$/; } - if ( $type == BPORT ) { + if ( $type & BPORT ) { if ( $zoneref->{bridge} eq '' ) { fatal_error 'Bridge Port Zones may only be associated with bridge ports' unless $interfaceref->{options}{port}; $zoneref->{bridge} = $interfaces{$interface}{bridge}; @@ -1807,14 +1792,14 @@ sub process_host( ) { } elsif ( $option eq 'blacklist' ) { $zoneref->{options}{in}{blacklist} = 1; } elsif ( $validhostoptions{$option}) { - fatal_error qq(The "$option" option is not allowed with Vserver zones) if $type == VSERVER && ! ( $validhostoptions{$option} & IF_OPTION_VSERVER ); + fatal_error qq(The "$option" option is not allowed with Vserver zones) if $type & VSERVER && ! ( $validhostoptions{$option} & IF_OPTION_VSERVER ); $options{$option} = 1; } else { fatal_error "Invalid option ($option)"; } } - fatal_error q(A host entry for a Vserver zone may not specify the 'ipsec' option) if $ipsec && $zoneref->{type} == VSERVER; + fatal_error q(A host entry for a Vserver zone may not specify the 'ipsec' option) if $ipsec && $zoneref->{type} & VSERVER; $optionsref = \%options; } @@ -1835,7 +1820,7 @@ sub process_host( ) { $hosts = join( '', ALLIP , $hosts ) if substr($hosts, 0, 2 ) eq ',!'; if ( $hosts eq 'dynamic' ) { - fatal_error "Vserver zones may not be dynamic" if $type == VSERVER; + fatal_error "Vserver zones may not be dynamic" if $type & VSERVER; require_capability( 'IPSET_MATCH', 'Dynamic nets', ''); my $physical = chain_base( physical_name $interface ); my $set = $family == F_IPV4 ? "${zone}_${physical}" : "6_${zone}_${physical}"; @@ -1847,7 +1832,7 @@ sub process_host( ) { # # We ignore the user's notion of what interface vserver addresses are on and simply invent one for all of the vservers. # - $interface = '%vserver%' if $type == VSERVER; + $interface = '%vserver%' if $type & VSERVER; add_group_to_zone( $zone, $type , $interface, [ split_list( $hosts, 'host' ) ] , $optionsref); @@ -1889,7 +1874,7 @@ sub find_hosts_by_option( $ ) { my $option = $_[0]; my @hosts; - for my $zone ( grep $zones{$_}{type} != FIREWALL , @zones ) { + for my $zone ( grep ! ( $zones{$_}{type} & FIREWALL ) , @zones ) { while ( my ($type, $interfaceref) = each %{$zones{$zone}{hosts}} ) { while ( my ( $interface, $arrayref) = ( each %{$interfaceref} ) ) { for my $host ( @{$arrayref} ) {