|
|
|
@ -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} ) {
|
|
|
|
|