From 5819589cb0a0fdf75621604c071855e48dc5399a Mon Sep 17 00:00:00 2001 From: teastep Date: Mon, 10 Sep 2007 22:28:06 +0000 Subject: [PATCH] First timid step toward IPv6 support git-svn-id: https://shorewall.svn.sourceforge.net/svnroot/shorewall/trunk@7313 fbd18981-670d-0410-9b5c-8dc0c1a9a2bb --- Shorewall-perl/Shorewall/Chains.pm | 4 +- Shorewall-perl/Shorewall/Policy.pm | 4 +- Shorewall-perl/Shorewall/Rules.pm | 20 +++---- Shorewall-perl/Shorewall/Tunnels.pm | 4 +- Shorewall-perl/Shorewall/Zones.pm | 86 ++++++++++++++++++++--------- 5 files changed, 77 insertions(+), 41 deletions(-) diff --git a/Shorewall-perl/Shorewall/Chains.pm b/Shorewall-perl/Shorewall/Chains.pm index 97b259961..8b2ed2af2 100644 --- a/Shorewall-perl/Shorewall/Chains.pm +++ b/Shorewall-perl/Shorewall/Chains.pm @@ -1245,7 +1245,7 @@ sub match_ipsec_in( $$ ) { my $zoneref = find_zone( $zone ); my $optionsref = $zoneref->{options}; - if ( $zoneref->{type} eq 'ipsec4' ) { + if ( $zoneref->{type} & ZT_IPSEC ) { $match .= "ipsec $optionsref->{in_out}{ipsec}$optionsref->{in}{ipsec}"; } elsif ( $capabilities{POLICY_MATCH} ) { $match .= "$hostref->{ipsec} $optionsref->{in_out}{ipsec}$optionsref->{in}{ipsec}"; @@ -1263,7 +1263,7 @@ sub match_ipsec_out( $$ ) { my $zoneref = find_zone( $zone ); my $optionsref = $zoneref->{options}; - if ( $zoneref->{type} eq 'ipsec4' ) { + if ( $zoneref->{type} & ZT_IPSEC ) { $match .= "ipsec $optionsref->{in_out}{ipsec}$optionsref->{out}{ipsec}"; } elsif ( $capabilities{POLICY_MATCH} ) { $match .= "$hostref->{ipsec} $optionsref->{in_out}{ipsec}$optionsref->{out}{ipsec}" diff --git a/Shorewall-perl/Shorewall/Policy.pm b/Shorewall-perl/Shorewall/Policy.pm index 46e882574..87dfadedb 100644 --- a/Shorewall-perl/Shorewall/Policy.pm +++ b/Shorewall-perl/Shorewall/Policy.pm @@ -266,11 +266,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 ) == ZT_FIREWALL ) || ( zone_type( $server ) == ZT_FIREWALL ); } unless ( $clientwild || $serverwild ) { - if ( zone_type( $server ) eq 'bport4' ) { + if ( zone_type( $server ) & ZT_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 e4d21e120..e606b32c6 100644 --- a/Shorewall-perl/Shorewall/Rules.pm +++ b/Shorewall-perl/Shorewall/Rules.pm @@ -1051,7 +1051,7 @@ sub process_rule1 ( $$$$$$$$$$$ ) { # # Check for illegal bridge port rule # - if ( $destref->{type} eq 'bport4' ) { + if ( $destref->{type} & ZT_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"; @@ -1175,7 +1175,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} == ZT_FIREWALL ? 'OUTPUT' : dnat_chain $sourcezone ), PREROUTE_RESTRICT , $rule , $source , @@ -1212,7 +1212,7 @@ sub process_rule1 ( $$$$$$$$$$$ ) { $origdest = $interfaces ? "detect:$interfaces" : ALLIPv4; } - expand_rule( ensure_chain ('nat' , $sourceref->{type} eq 'firewall' ? 'OUTPUT' : dnat_chain $sourcezone) , + expand_rule( ensure_chain ('nat' , $sourceref->{type} == ZT_FIREWALL ? 'OUTPUT' : dnat_chain $sourcezone) , PREROUTE_RESTRICT , $rule , $source , @@ -1315,10 +1315,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 ) != ZT_FIREWALL ) ) { if ( $dest eq 'all' ) { for my $zone1 ( all_zones ) { - if ( $includedstfw || ( zone_type( $zone1 ) ne 'firewall' ) ) { + if ( $includedstfw || ( zone_type( $zone1 ) != ZT_FIREWALL ) ) { if ( $intrazone || ( $zone ne $zone1 ) ) { process_rule1 $target, $zone, $zone1 , $proto, $ports, $sports, $origdest, $ratelimit, $user, $mark, 1; } @@ -1336,7 +1336,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 ) != ZT_FIREWALL ) ) && ( ( $sourcezone ne $zone ) || $intrazone) ) { process_rule1 $target, $source, $zone , $proto, $ports, $sports, $origdest, $ratelimit, $user, $mark, 1; } } @@ -1528,11 +1528,11 @@ sub generate_matrix() { if ( $capabilities{POLICY_MATCH} ) { my $type = $zoneref->{type}; - my $source_ref = ( $zoneref->{hosts}{ipsec4} ) || {}; + my $source_ref = ( $zoneref->{hosts}{+ZT_IPSEC4} ) || {}; if ( $config{DYNAMIC_ZONES} ) { no warnings; - create_zone_dyn_chain $zone, $frwd_ref if (%$source_ref || $type eq 'ipsec4' ); + create_zone_dyn_chain $zone, $frwd_ref if (%$source_ref || $type & ZT_IPSEC ); } for my $interface ( keys %$source_ref ) { @@ -1671,7 +1671,7 @@ sub generate_matrix() { next if ( scalar ( keys( %{ $zoneref->{interfaces}} ) ) < 2 ) && ! ( $zoneref->{options}{in_out}{routeback} || @$exclusions ); } - if ( $zone1ref->{type} eq 'bport4' ) { + if ( $zone1ref->{type} & ZT_BPORT ) { next unless $zoneref->{bridge} eq $zone1ref->{bridge}; } @@ -1736,7 +1736,7 @@ sub generate_matrix() { } } - if ( $zone1ref->{type} eq 'bport4' ) { + if ( $zone1ref->{type} & ZT_BPORT ) { next ZONE1 unless $zoneref->{bridge} eq $zone1ref->{bridge}; } diff --git a/Shorewall-perl/Shorewall/Tunnels.pm b/Shorewall-perl/Shorewall/Tunnels.pm index 0e19c0680..4bdd40554 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 /,/, $gatewayzones ) { my $type = zone_type( $zone ); - fatal_error "Invalid zone ($zone) for GATEWAY ZONE" if $type eq 'firewall' || $type eq 'bport4'; + fatal_error "Invalid zone ($zone) for GATEWAY ZONE" if $type == ZT_FIREWALL || $type & ZT_BPORT; $inchainref = ensure_filter_chain "${zone}2${fw}", 1; $outchainref = ensure_filter_chain "${fw}2${zone}", 1; @@ -228,7 +228,7 @@ sub setup_tunnels() { my $zonetype = zone_type( $zone ); - fatal_error "Invalid zone ($zone) for tunnel ZONE" if $zonetype eq 'firewall' || $zonetype eq 'bport4'; + fatal_error "Invalid zone ($zone) for tunnel ZONE" if $zonetype == ZT_FIREWALL || $zonetype & ZT_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 ee9f54866..23fd1d811 100644 --- a/Shorewall-perl/Shorewall/Zones.pm +++ b/Shorewall-perl/Shorewall/Zones.pm @@ -37,6 +37,16 @@ our @EXPORT = qw( NOTHING IPSECPROTO IPSECMODE + ZT_IPV4 + ZT_IPSEC + ZT_BPORT + ZT_IPV6 + ZT_IPSEC4 + ZT_IPSEC6 + ZT_BPORT4 + ZT_BPORT6 + ZT_FIREWALL + numeric_value determine_zones zone_report @@ -81,7 +91,7 @@ use constant { NOTHING => 'NOTHING', # # @zones contains the ordered list of zones with sub-zones appearing before their parents. # -# %zones{ => {type = > 'firewall', 'ipv4', 'ipsec4', 'bport4'; +# %zones{ => {type = > (see above). # options => { complex => 0|1 # in_out => < policy match string > # in => < policy match string > @@ -116,6 +126,27 @@ our %reservedName = ( all => 1, DEST => 1 ); # +# Zone Types +# +use constant { ZT_IPV4 => 1, + ZT_IPSEC => 2, + ZT_BPORT => 4, + ZT_IPV6 => 8, + ZT_FIREWALL => 16, + ZT_IPSEC4 => 3, + ZT_IPSEC6 => 10, + ZT_BPORT4 => 5, + ZT_BPORT6 => 13, + }; + +our %zonetypes = ( 1 => 'ipv4' , + 3 => 'ipsec4' , + 5 => 'bport4' , + 8 => 'ipv6' , + 10 => 'ipsec6' , + 13 => 'bport6' , + 16 => 'firewall' ); +# # Interface Table. # # @interfaces lists the interface names in the order that they appear in the interfaces file. @@ -223,7 +254,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 'ipsec4'; + fatal_error "The \"$e\" option may only be specified for ipsec zones" unless ( $zonetype & ZT_IPSEC ); $options .= $invert; $options .= "--$e "; $options .= "$val "if defined $val; @@ -265,7 +296,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} == ZT_FIREWALL; push @{$zones{$p}{children}}, $zone; } } @@ -277,20 +308,25 @@ sub determine_zones() $type = "ipv4" unless $type; if ( $type =~ /ipv4/i ) { - $type = 'ipv4'; + $type = ZT_IPV4; } elsif ( $type =~ /^ipsec4?$/i ) { - $type = 'ipsec4'; + $type = ZT_IPSEC4; + } elsif ( $type =~ /^ipsec6$/i ) { + $type = ZT_IPSEC6; } elsif ( $type =~ /^bport4?$/i ) { warning_message "Bridge Port zones should have a parent zone" unless @parents; - $type = 'bport4'; + $type = ZT_BPORT4; + } elsif ( $type =~ /^bport6$/i ) { + warning_message "Bridge Port zones should have a parent zone" unless @parents; + $type = ZT_BPORT6; } 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 = ZT_FIREWALL; } elsif ( $type eq '-' ) { - $type = 'ipv4'; + $type = ZT_IPV4; } else { fatal_error "Invalid zone type ($type)" ; } @@ -306,7 +342,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 'ipsec4' || $options || $in_options || $out_options ? 1 : 0) } , + complex => ( ( $type & ZT_IPSEC ) || $options || $in_options || $out_options ? 1 : 0) } , interfaces => {} , children => [] , hosts => {} @@ -341,7 +377,7 @@ sub determine_zones() # sub haveipseczones() { for my $zoneref ( values %zones ) { - return 1 if $zoneref->{type} eq 'ipsec4'; + return 1 if ( $zoneref->{type} & ZT_IPSEC ); } 0; @@ -361,7 +397,7 @@ sub zone_report() my $type = $zoneref->{type}; my $optionref = $zoneref->{options}; - progress_message " $zone ($type)"; + progress_message " $zone ($zonetypes{$type})"; my $printed = 0; @@ -385,8 +421,8 @@ sub zone_report() } unless ( $printed ) { - fatal_error "No bridge has been associated with zone $zone" if $type eq 'bport4' && ! $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 & ZT_BPORT ) && ! $zoneref->{bridge}; + warning_message "*** $zone is an EMPTY ZONE ***" unless $type == ZT_FIREWALL; } } @@ -401,9 +437,9 @@ sub dump_zone_contents() my $type = $zoneref->{type}; my $optionref = $zoneref->{options}; my $exclusions = $zoneref->{exclusions}; - my $entry = "$zone $type"; + my $entry = "$zone $zonetypes{$type}"; - $entry .= ":$zoneref->{bridge}" if $type eq 'bport4'; + $entry .= ":$zoneref->{bridge}" if $type & ZT_BPORT; if ( $hostref ) { for my $type ( sort keys %$hostref ) { @@ -478,7 +514,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 ALLIPv4; } @@ -505,7 +541,7 @@ sub add_group_to_zone($$$$$) push @{$arrayref}, { options => $options, hosts => \@newnetworks, - ipsec => $type eq 'ipsec4' ? 'ipsec' : 'none' }; + ipsec => $type & ZT_IPSEC ? 'ipsec' : 'none' }; } # @@ -535,7 +571,7 @@ sub all_zones() { } sub non_firewall_zones() { - grep ( $zones{$_}{type} ne 'firewall' , @zones ); + grep ( $zones{$_}{type} != ZT_FIREWALL , @zones ); } sub complex_zones() { @@ -631,7 +667,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} == ZT_FIREWALL; } $networks = '' if $networks eq '-'; @@ -648,7 +684,7 @@ sub validate_interfaces_file( $ ) 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 "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} & ZT_BPORT ); if ( $zone ) { if ( $zoneref->{bridge} ) { @@ -668,7 +704,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 'bport4'; + fatal_error "Zones of type 'bport' may only be associated with bridge ports" if $zone && $zoneref->{type} & ZT_BPORT; $interfaces{$interface}{bridge} = $interface; } @@ -934,7 +970,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 == ZT_FIREWALL; my $interface; @@ -947,7 +983,7 @@ sub validate_hosts_file() fatal_error "Invalid HOST(S) column contents: $hosts"; } - if ( $type eq 'bport4' ) { + if ( $type & ZT_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}; @@ -965,7 +1001,7 @@ sub validate_hosts_file() for my $option ( @options ) { if ( $option eq 'ipsec' ) { - $type = 'ipsec4'; + $type = ZT_IPSEC4; $zoneref->{options}{complex} = 1; $ipsec = 1; } elsif ( $validoptions{$option}) { @@ -1008,7 +1044,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} != ZT_FIREWALL , @zones ) { while ( my ($type, $interfaceref) = each %{$zones{$zone}{hosts}} ) { while ( my ( $interface, $arrayref) = ( each %{$interfaceref} ) ) { for my $host ( @{$arrayref} ) {