From 229e573c3c03a0b56bcf36aefa9d899599b71755 Mon Sep 17 00:00:00 2001 From: teastep Date: Fri, 13 Mar 2009 22:59:49 +0000 Subject: [PATCH] Make zone type numeric for faster comparison Signed-off-by: Tom Eastep git-svn-id: https://shorewall.svn.sourceforge.net/svnroot/shorewall/trunk@9684 fbd18981-670d-0410-9b5c-8dc0c1a9a2bb --- Shorewall/Perl/Shorewall/Policy.pm | 4 +- Shorewall/Perl/Shorewall/Rules.pm | 16 ++--- Shorewall/Perl/Shorewall/Tunnels.pm | 4 +- Shorewall/Perl/Shorewall/Zones.pm | 94 ++++++++++++++++------------- 4 files changed, 64 insertions(+), 54 deletions(-) diff --git a/Shorewall/Perl/Shorewall/Policy.pm b/Shorewall/Perl/Shorewall/Policy.pm index 09b002591..3b45681d1 100644 --- a/Shorewall/Perl/Shorewall/Policy.pm +++ b/Shorewall/Perl/Shorewall/Policy.pm @@ -265,11 +265,11 @@ sub validate_policy() fatal_error "NONE policy not allowed with \"all\"" if $clientwild || $serverwild; fatal_error "NONE policy not allowed to/from firewall zone" - if ( zone_type( $client ) eq 'firewall' ) || ( zone_type( $server ) eq 'firewall' ); + if ( zone_type( $client ) == FIREWALL ) || ( zone_type( $server ) == FIREWALL ); } unless ( $clientwild || $serverwild ) { - if ( zone_type( $server ) eq '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}; } diff --git a/Shorewall/Perl/Shorewall/Rules.pm b/Shorewall/Perl/Shorewall/Rules.pm index 46f14d4f2..5d2e1ae00 100644 --- a/Shorewall/Perl/Shorewall/Rules.pm +++ b/Shorewall/Perl/Shorewall/Rules.pm @@ -1201,7 +1201,7 @@ sub process_rule1 ( $$$$$$$$$$$$$ ) { # # Check for illegal bridge port rule # - if ( $destref->{type} eq 'bport' ) { + if ( $destref->{type} == BPORT ) { unless ( $sourceref->{bridge} eq $destref->{bridge} || single_interface( $sourcezone ) eq $destref->{bridge} ) { return 1 if $wildcard; fatal_error "Rules with a DESTINATION Bridge Port zone must have a SOURCE zone on the same bridge"; @@ -1356,7 +1356,7 @@ sub process_rule1 ( $$$$$$$$$$$$$ ) { # # And generate the nat table rule(s) # - expand_rule ( ensure_chain ('nat' , $sourceref->{type} eq 'firewall' ? 'OUTPUT' : dnat_chain $sourcezone ), + expand_rule ( ensure_chain ('nat' , $sourceref->{type} == FIREWALL ? 'OUTPUT' : dnat_chain $sourcezone ), PREROUTE_RESTRICT , $rule , $source , @@ -1394,7 +1394,7 @@ sub process_rule1 ( $$$$$$$$$$$$$ ) { $origdest = $interfaces ? "detect:$interfaces" : ALLIP; } - expand_rule( ensure_chain ('nat' , $sourceref->{type} eq 'firewall' ? 'OUTPUT' : dnat_chain $sourcezone) , + expand_rule( ensure_chain ('nat' , $sourceref->{type} == 'FIREWALL' ? 'OUTPUT' : dnat_chain $sourcezone) , PREROUTE_RESTRICT , $rule , $source , @@ -1500,10 +1500,10 @@ sub process_rule ( $$$$$$$$$$$$ ) { if ( $source eq 'all' ) { for my $zone ( all_zones ) { - if ( $includesrcfw || ( zone_type( $zone ) ne 'firewall' ) ) { + if ( $includesrcfw || ( zone_type( $zone ) != FIREWALL ) ) { if ( $dest eq 'all' ) { for my $zone1 ( all_zones ) { - if ( $includedstfw || ( zone_type( $zone1 ) ne 'firewall' ) ) { + if ( $includedstfw || ( zone_type( $zone1 ) != FIREWALL ) ) { if ( $intrazone || ( $zone ne $zone1 ) ) { process_rule1 $target, $zone, $zone1 , $proto, $ports, $sports, $origdest, $ratelimit, $user, $mark, $connlimit, $time, 1; } @@ -1521,7 +1521,7 @@ sub process_rule ( $$$$$$$$$$$$ ) { } elsif ( $dest eq 'all' ) { for my $zone ( all_zones ) { my $sourcezone = ( split( /:/, $source, 2 ) )[0]; - if ( ( $includedstfw || ( zone_type( $zone ) ne 'firewall') ) && ( ( $sourcezone ne $zone ) || $intrazone) ) { + if ( ( $includedstfw || ( zone_type( $zone ) != FIREWALL ) ) && ( ( $sourcezone ne $zone ) || $intrazone) ) { process_rule1 $target, $source, $zone , $proto, $ports, $sports, $origdest, $ratelimit, $user, $mark, $connlimit, $time, 1; } } @@ -1901,7 +1901,7 @@ sub generate_matrix() { next if ( scalar ( keys( %{ $zoneref->{interfaces}} ) ) < 2 ) && ! $zoneref->{options}{in_out}{routeback}; } - if ( $zone1ref->{type} eq 'bport' ) { + if ( $zone1ref->{type} == BPORT ) { next unless $zoneref->{bridge} eq $zone1ref->{bridge}; } @@ -1953,7 +1953,7 @@ sub generate_matrix() { next ZONE1 if ( $num_ifaces = scalar( keys ( %{$zoneref->{interfaces}} ) ) ) < 2 && ! $zoneref->{options}{in_out}{routeback}; } - if ( $zone1ref->{type} eq 'bport' ) { + if ( $zone1ref->{type} == BPORT ) { next ZONE1 unless $zoneref->{bridge} eq $zone1ref->{bridge}; } diff --git a/Shorewall/Perl/Shorewall/Tunnels.pm b/Shorewall/Perl/Shorewall/Tunnels.pm index b03c60fe2..2673f730f 100644 --- a/Shorewall/Perl/Shorewall/Tunnels.pm +++ b/Shorewall/Perl/Shorewall/Tunnels.pm @@ -82,7 +82,7 @@ sub setup_tunnels() { unless ( $gatewayzones eq '-' ) { for my $zone ( split_list $gatewayzones, 'zone' ) { my $type = zone_type( $zone ); - fatal_error "Invalid zone ($zone) for GATEWAY ZONE" if $type eq 'firewall' || $type eq 'bport'; + fatal_error "Invalid zone ($zone) for GATEWAY ZONE" if $type == FIREWALL || $type == BPORT; $inchainref = ensure_filter_chain "${zone}2${fw}", 1; $outchainref = ensure_filter_chain "${fw}2${zone}", 1; @@ -237,7 +237,7 @@ sub setup_tunnels() { my $zonetype = zone_type( $zone ); - fatal_error "Invalid tunnel ZONE ($zone)" if $zonetype eq 'firewall' || $zonetype eq 'bport'; + fatal_error "Invalid tunnel ZONE ($zone)" if $zonetype == FIREWALL || $zonetype == BPORT; my $inchainref = ensure_filter_chain "${zone}2${fw}", 1; my $outchainref = ensure_filter_chain "${fw}2${zone}", 1; diff --git a/Shorewall/Perl/Shorewall/Zones.pm b/Shorewall/Perl/Shorewall/Zones.pm index 8f493dc4d..bc75af9b8 100644 --- a/Shorewall/Perl/Shorewall/Zones.pm +++ b/Shorewall/Perl/Shorewall/Zones.pm @@ -36,6 +36,10 @@ our @EXPORT = qw( NOTHING NETWORK IPSECPROTO IPSECMODE + FIREWALL + IP + BPORT + IPSEC determine_zones zone_report @@ -85,7 +89,7 @@ use constant { NOTHING => 'NOTHING', # # @zones contains the ordered list of zones with sub-zones appearing before their parents. # -# %zones{ => {type = > 'firewall', 'ip', 'ipsec', 'bport'; +# %zones{ => {type = > FIREWALL, IP, IPSEC, BPORT; # options => { complex => 0|1 # nested => 0|1 # in_out => < policy match string > @@ -145,13 +149,19 @@ our @bport_zones; our %ipsets; our $family; +use constant { FIREWALL => 1, + IP => 2, + BPORT => 3, + IPSEC => 4 }; + # # Initialize globals -- we take this novel approach to globals initialization to allow # the compiler to run multiple times in the same process. The # initialize() function does globals initialization for this # module and is called from an INIT block below. The function is # also called by Shorewall::Compiler::compiler at the beginning of -# the second and subsequent calls to that function. +# the second and subsequent calls to that function or when compiling +# for IPv6. # sub initialize( $ ) { @@ -226,7 +236,7 @@ sub parse_zone_option_list($$) if ( $key{$e} ) { $h{$e} = $val; } else { - fatal_error "The \"$e\" option may only be specified for ipsec zones" unless $zonetype eq '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; @@ -265,7 +275,7 @@ sub determine_zones() 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} eq 'firewall'; + fatal_error 'Subzones of firewall zone not allowed' if $zones{$p}{type} == FIREWALL; push @{$zones{$p}{children}}, $zone; } } @@ -274,32 +284,32 @@ sub determine_zones() fatal_error "Invalid zone name ($zone)" if $reservedName{$zone} || $zone =~ /^all2|2all$/; fatal_error( "Duplicate zone name ($zone)" ) if $zones{$zone}; - $type = "ip" unless $type; + $type = IP unless $type; if ( $type =~ /ipv4/i ) { fatal_error "Invalid zone type ($type)" if $family == F_IPV6; - $type = 'ip'; + $type = IP; $ip = 1; } elsif ( $type =~ /ipv6/i ) { fatal_error "Invalid zone type ($type)" if $family == F_IPV4; - $type = 'ip'; + $type = IP; $ip = 1; } elsif ( $type =~ /^ipsec([46])?$/i ) { fatal_error "Invalid zone type ($type)" if $1 && (($1 == 4 && $family == F_IPV6 ) || ( $1 == 6 && $family == F_IPV4 )); - $type = 'ipsec'; + $type = IPSEC; } elsif ( $type =~ /^bport([46])?$/i ) { fatal_error "Invalid zone type ($type)" if $1 && (( $1 == 4 && $family == F_IPV6 ) || ( $1 == 6 && $family == F_IPV4 )); warning_message "Bridge Port zones should have a parent zone" unless @parents; - $type = 'bport'; + $type = BPORT; push @bport_zones, $zone; } elsif ( $type eq 'firewall' ) { fatal_error 'Firewall zone may not be nested' if @parents; fatal_error "Only one firewall zone may be defined ($zone)" if $firewall_zone; $firewall_zone = $zone; $ENV{FW} = $zone; - $type = "firewall"; + $type = FIREWALL; } elsif ( $type eq '-' ) { - $type = 'ip'; + $type = IP; $ip = 1; } else { fatal_error "Invalid zone type ($type)" ; @@ -315,7 +325,7 @@ sub determine_zones() options => { in_out => parse_zone_option_list( $options || '', $type ) , in => parse_zone_option_list( $in_options || '', $type ) , out => parse_zone_option_list( $out_options || '', $type ) , - complex => ($type eq 'ipsec' || $options || $in_options || $out_options ? 1 : 0) , + complex => ($type == IPSEC || $options || $in_options || $out_options ? 1 : 0) , nested => @parents > 0 } , interfaces => {} , children => [] , @@ -353,7 +363,7 @@ sub determine_zones() # sub haveipseczones() { for my $zoneref ( values %zones ) { - return 1 if $zoneref->{type} eq 'ipsec'; + return 1 if $zoneref->{type} == IPSEC; } 0; @@ -366,7 +376,13 @@ sub zone_report() { progress_message2 "Determining Hosts in Zones..."; - my $ipzone = $family == F_IPV4 ? 'ipv4' : 'ipv6'; + my @translate; + + if ( $family == F_IPV4 ) { + @translate = ( undef, 'firewall', 'ipv4', 'bport4', 'ipsec4' ); + } else { + @translate = ( undef, 'firewall', 'ipv6', 'bport6', 'ipsec6' ); + } for my $zone ( @zones ) { @@ -375,9 +391,7 @@ sub zone_report() my $type = $zoneref->{type}; my $optionref = $zoneref->{options}; - $type = $ipzone if $type eq 'ip'; - - progress_message_nocompress " $zone ($type)"; + progress_message_nocompress " $zone ($translate[$type])"; my $printed = 0; @@ -407,8 +421,8 @@ sub zone_report() } unless ( $printed ) { - fatal_error "No bridge has been associated with zone $zone" if $type eq 'bport' && ! $zoneref->{bridge}; - warning_message "*** $zone is an EMPTY ZONE ***" unless $type eq 'firewall'; + 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; } } @@ -416,16 +430,12 @@ sub zone_report() sub dump_zone_contents() { - my %xlate; + my @xlate; if ( $family == F_IPV4 ) { - %xlate = ( ip => 'ipv4' , - bport => 'bport4' , - ipsec => 'ipsec4' ) - } else { - %xlate = ( ip => 'ipv6' , - bport => 'bport6' , - ipsec => 'ipsec6' ) + @xlate = ( undef, 'firewall', 'ipv4', 'bport4', 'ipsec4' ); + } else { + @xlate = ( undef, 'firewall', 'ipv6', 'bport6', 'ipsec6' ); } for my $zone ( @zones ) @@ -435,11 +445,9 @@ sub dump_zone_contents() my $type = $zoneref->{type}; my $optionref = $zoneref->{options}; - $type = $xlate{$type} if $xlate{$type}; + my $entry = "$zone $xlate[$type]"; - my $entry = "$zone $type"; - - $entry .= ":$zoneref->{bridge}" if $type =~ /^bport/; + $entry .= ":$zoneref->{bridge}" if $type == BPORT; if ( $hostref ) { for my $type ( sort keys %$hostref ) { @@ -517,7 +525,7 @@ sub add_group_to_zone($$$$$) } unless ( $switched ) { - if ( $type eq $zonetype ) { + if ( $type == $zonetype ) { fatal_error "Duplicate Host Group ($interface:$host) in zone $zone" if $ifacezone eq $zone; $ifacezone = $zone if $host eq ALLIP; } @@ -535,15 +543,17 @@ sub add_group_to_zone($$$$$) $zoneref->{options}{in_out}{routeback} = 1 if $options->{routeback}; + my $gtype = $type == IPSEC ? 'ipsec' : 'ip'; + $hostsref = ( $zoneref->{hosts} || ( $zoneref->{hosts} = {} ) ); - $typeref = ( $hostsref->{$type} || ( $hostsref->{$type} = {} ) ); + $typeref = ( $hostsref->{$gtype} || ( $hostsref->{$gtype} = {} ) ); $interfaceref = ( $typeref->{$interface} || ( $typeref->{$interface} = [] ) ); $zoneref->{options}{complex} = 1 if @$interfaceref || ( @newnetworks > 1 ) || ( @exclusions ); push @{$interfaceref}, { options => $options, hosts => \@newnetworks, - ipsec => $type eq 'ipsec' ? 'ipsec' : 'none' , + ipsec => $type == IPSEC ? 'ipsec' : 'none' , exclusions => \@exclusions }; } @@ -578,7 +588,7 @@ sub all_zones() { } sub non_firewall_zones() { - grep ( $zones{$_}{type} ne 'firewall' , @zones ); + grep ( $zones{$_}{type} != FIREWALL , @zones ); } sub complex_zones() { @@ -675,7 +685,7 @@ sub validate_interfaces_file( $ ) $zoneref = $zones{$zone}; fatal_error "Unknown zone ($zone)" unless $zoneref; - fatal_error "Firewall zone not allowed in ZONE column of interface record" if $zoneref->{type} eq 'firewall'; + fatal_error "Firewall zone not allowed in ZONE column of interface record" if $zoneref->{type} == FIREWALL; } $networks = '' if $networks eq '-'; @@ -691,7 +701,7 @@ sub validate_interfaces_file( $ ) fatal_error "Your iptables is not recent enough to support bridge ports" unless $capabilities{KLUDGEFREE}; 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 "Bridge Ports may only be associated with 'bport' zones" if $zone && $zoneref->{type} ne 'bport'; + fatal_error "Bridge Ports may only be associated with 'bport' zones" if $zone && $zoneref->{type} != BPORT; if ( $zone ) { if ( $zoneref->{bridge} ) { @@ -709,7 +719,7 @@ sub validate_interfaces_file( $ ) $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} eq 'bport'; + fatal_error "Zones of type 'bport' may only be associated with bridge ports" if $zone && $zoneref->{type} == BPORT; $bridge = $interface; } @@ -1054,7 +1064,7 @@ sub validate_hosts_file() my $type = $zoneref->{type}; fatal_error "Unknown ZONE ($zone)" unless $type; - fatal_error 'Firewall zone not allowed in ZONE column of hosts record' if $type eq 'firewall'; + fatal_error 'Firewall zone not allowed in ZONE column of hosts record' if $type == FIREWALL; my $interface; @@ -1078,7 +1088,7 @@ sub validate_hosts_file() } } - if ( $type eq 'bport' ) { + if ( $type == BPORT ) { if ( $zoneref->{bridge} eq '' ) { fatal_error 'Bridge Port Zones may only be associated with bridge ports' unless $interfaces{$interface}{options}{port}; $zoneref->{bridge} = $interfaces{$interface}{bridge}; @@ -1096,7 +1106,7 @@ sub validate_hosts_file() for my $option ( @options ) { if ( $option eq 'ipsec' ) { - $type = 'ipsec'; + $type = IPSEC; $zoneref->{options}{complex} = 1; $ipsec = 1; } elsif ( $validoptions{$option}) { @@ -1148,7 +1158,7 @@ sub find_hosts_by_option( $ ) { my $option = $_[0]; my @hosts; - for my $zone ( grep $zones{$_}{type} ne '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} ) {