Sort specific hash keys and values if -t

Signed-off-by: Tom Eastep <teastep@shorewall.net>
This commit is contained in:
Tom Eastep 2020-04-07 11:11:09 -07:00
parent 6dc99e77ae
commit a49a9f9f9d
No known key found for this signature in database
GPG Key ID: 96E6B3F2423A4D10
7 changed files with 117 additions and 77 deletions

View File

@ -37,6 +37,7 @@ use Shorewall::Config qw(:DEFAULT :internal);
use Shorewall::Zones;
use Shorewall::IPAddrs;
use strict;
use sort 'stable';
our @ISA = qw(Exporter);
our @EXPORT = ( qw(
@ -3706,6 +3707,24 @@ sub optimize_level0() {
}
}
#
# Conditionally sort a list of chain table entry references by name, if -t was specified
#
sub keysort(\%) {
my $hashref = shift;
return sort { $a->{name} cmp $b->{name} } keys %$hashref if $test;
return keys %$hashref;
}
sub valuesort(\%) {
my $hashref = shift;
return sort { $a->{name} cmp $b->{name} } values %$hashref if $test;
return values %$hashref;
}
sub optimize_level4( $$ ) {
my ( $table, $tableref ) = @_;
my $progress = 1;
@ -3927,7 +3946,7 @@ sub optimize_level4( $$ ) {
my @chains = grep ( $_->{referenced} &&
! $_->{optflags} &&
@{$_->{rules}} < 4 &&
keys %{$_->{references}} == 1 , values %$tableref );
keys %{$_->{references}} == 1 , valuesort %$tableref );
if ( my $chains = @chains ) {
$passes++;
@ -3936,7 +3955,7 @@ sub optimize_level4( $$ ) {
for my $chainref ( @chains ) {
my $name = $chainref->{name};
for my $sourceref ( map $tableref->{$_}, keys %{$chainref->{references}} ) {
for my $sourceref ( map $tableref->{$_}, sortkeysiftest %{$chainref->{references}} ) {
my $name1 = $sourceref->{name};
if ( $chainref->{references}{$name1} == 1 ) {
@ -4066,7 +4085,7 @@ sub optimize_level8( $$$ ) {
#
# First create aliases for each renamed chain and change the {name} member.
#
for my $oldname ( @rename ) {
for my $oldname ( sortiftest @rename ) {
my $newname = $renamed{ $oldname } = $rename{ $oldname } . $chainseq++;
trace( $tableref->{$oldname}, 'RN', 0, " Renamed $newname" ) if $debug;
@ -4579,7 +4598,7 @@ sub combine_states {
sub optimize_level16( $$$ ) {
my ( $table, $tableref , $passes ) = @_;
my @chains = ( grep $_->{referenced}, values %{$tableref} );
my @chains = ( grep $_->{referenced}, valuesort %{$tableref} );
my @chains1 = @chains;
my $chains = @chains;
@ -4696,7 +4715,7 @@ sub setup_zone_mss() {
my $hosts = find_zone_hosts_by_option( $zone, 'mss' );
for my $hostref ( @$hosts ) {
for my $hostref ( $test ? sort { $a->[0] cmp $b->[0] } @$hosts : @$hosts ) {
my $mss = $hostref->[4];
my @mssmatch = have_capability( 'TCPMSS_MATCH' ) ? ( tcpmss => "--mss $mss:" ) : ();
my @sourcedev = imatch_source_dev $hostref->[0];
@ -7455,13 +7474,13 @@ sub set_global_variables( $$ ) {
if ( $conditional ) {
my ( $interface, @interfaces );
@interfaces = keys %interfaceaddr;
@interfaces = sortkeysiftest %interfaceaddr;
for $interface ( @interfaces ) {
emit( qq([ -z "\$interface" -o "\$interface" = "$interface" ] && $interfaceaddr{$interface}) );
}
@interfaces = keys %interfacegateways;
@interfaces = sortkeysiftest %interfacegateways;
for $interface ( @interfaces ) {
emit( qq(if [ -z "\$interface" -o "\$interface" = "$interface" ]; then) );
@ -7471,29 +7490,29 @@ sub set_global_variables( $$ ) {
emit( qq(fi\n) );
}
@interfaces = keys %interfacemacs;
@interfaces = sortkeysiftest %interfacemacs;
for $interface ( @interfaces ) {
emit( qq([ -z "\$interface" -o "\$interface" = "$interface" ] && $interfacemacs{$interface}) );
}
} else {
emit $_ for values %interfaceaddr;
emit "$_\n" for values %interfacegateways;
emit $_ for values %interfacemacs;
emit $interfaceaddr{$_} for sortkeysiftest %interfaceaddr;
emit "$interfacegateways{$_}\n" for sortkeysiftest %interfacegateways;
emit $interfacemacs{$_} for sortkeysiftest %interfacemacs;
}
if ( $setall ) {
emit $_ for values %interfaceaddrs;
emit $_ for values %interfacenets;
emit $interfaceaddr{$_} for sortkeysiftest %interfaceaddr;
emit $interfacenets{$_} for sortkeysiftest %interfacenets;
unless ( have_capability( 'ADDRTYPE' ) ) {
if ( $family == F_IPV4 ) {
emit 'ALL_BCASTS="$(get_all_bcasts) 255.255.255.255"';
emit $_ for values %interfacebcasts;
emit $interfacebcasts{$_} for sortkeysiftest %interfacebcasts;
} else {
emit 'ALL_ACASTS="$(get_all_acasts)"';
emit $_ for values %interfaceacasts;
emit $interfaceacasts{$_} for sortkeysiftest %interfaceacasts;
}
}
}
@ -8457,7 +8476,7 @@ sub add_interface_options( $ ) {
# Insert jumps to the interface chains into the rules chains
#
for my $zone1 ( off_firewall_zones ) {
my @input_interfaces = keys %{zone_interfaces( $zone1 )};
my @input_interfaces = sortkeysiftest %{zone_interfaces( $zone1 )};
my @forward_interfaces = @input_interfaces;
if ( @input_interfaces > 1 ) {
@ -8543,7 +8562,7 @@ sub add_interface_options( $ ) {
for my $zone1 ( firewall_zone, vserver_zones ) {
for my $zone2 ( off_firewall_zones ) {
my $chainref = $filter_table->{rules_chain( $zone1, $zone2 )};
my @interfaces = keys %{zone_interfaces( $zone2 )};
my @interfaces = sortkeysiftest %{zone_interfaces( $zone2 )};
my $chain1ref;
for my $interface ( @interfaces ) {
@ -8984,7 +9003,7 @@ sub create_save_ipsets() {
#
$ipsets{$_} = 1 for ( @ipsets, @{$globals{SAVED_IPSETS}} );
my @sets = keys %ipsets;
my @sets = sortkeysiftest %ipsets;
emit( '' ,
' rm -f $file' ,
@ -9153,7 +9172,7 @@ sub create_load_ipsets() {
#
sub create_nfobjects() {
my @objects = ( keys %nfobjects );
my @objects = ( sortkeysiftest %nfobjects );
if ( @objects ) {
if ( $config{NFACCT} ) {
@ -9168,7 +9187,7 @@ sub create_nfobjects() {
}
}
for ( keys %nfobjects ) {
for ( @objects ) {
emit( qq(if ! qt \$NFACCT get $_; then),
qq( \$NFACCT add $_),
qq(fi\n) );
@ -9541,7 +9560,7 @@ sub create_stop_load( $ ) {
}
sub initialize_switches() {
if ( keys %switches ) {
if ( sortkeysiftest %switches ) {
emit( 'if [ $COMMAND = start ]; then' );
push_indent;
for my $switch ( keys %switches ) {

View File

@ -49,8 +49,6 @@ our $VERSION = 'MODULEVERSION';
our $export; # True when compiling for export
our $test; # True when running regression tests
our $family; # IP address family (4 or 6)
our $have_arptables; # True if we have arptables rules
@ -58,8 +56,8 @@ our $have_arptables; # True if we have arptables rules
#
# Initilize the package-globals in the other modules
#
sub initialize_package_globals( $$$ ) {
Shorewall::Config::initialize($family, $export, $_[1], $_[2]);
sub initialize_package_globals( $$$$ ) {
Shorewall::Config::initialize($family, $export, $_[1], $_[2], $_[3]);
Shorewall::Chains::initialize ($family, 1, $export );
Shorewall::Zones::initialize ($family, $_[0]);
Shorewall::Nat::initialize($family);
@ -588,7 +586,7 @@ sub compiler {
( '', '', -1, '', 0, '', -1, 0, 0, 0, 0, , '' , '/usr/share/shorewall/shorewallrc', '' );
$export = 0;
$test = 0;
my $test = 0;
$have_arptables = 0;
sub validate_boolean( $ ) {
@ -641,18 +639,19 @@ sub compiler {
#
# Now that we know the address family (IPv4/IPv6), we can initialize the other modules' globals
#
initialize_package_globals( $update, $shorewallrc, $shorewallrc1 );
initialize_package_globals( $update, $test, $shorewallrc, $shorewallrc1 );
#
# Rather than continuing to extend the argument list of Config::initialize(),
# we use a set of small functions to export settings to the Config module.
#
set_config_path( $config_path ) if $config_path;
set_shorewall_dir( $directory ) if $directory ne '';
$verbosity = 1 if $debug && $verbosity < 1;
set_verbosity( $verbosity );
set_log($log, $log_verbosity) if $log;
set_timestamp( $timestamp );
set_debug( $debug , $confess );
set_command( 'compile', 'Compiling', 'Compiled' );
#
# S H O R E W A L L R C ,
# S H O R E W A L L . C O N F A N D C A P A B I L I T I E S
@ -670,12 +669,7 @@ sub compiler {
#
# Create a temp file to hold the script
#
if ( $scriptfilename ) {
set_command( 'compile', 'Compiling', 'Compiled' );
create_temp_script( $scriptfilename , $export );
} else {
set_command( 'check', 'Checking', 'Checked' );
}
create_temp_script( $scriptfilename , $export ) if $scriptfilename;
#
# Z O N E D E F I N I T I O N
# (Produces no output to the compiled script)

View File

@ -166,7 +166,11 @@ our @EXPORT = qw(
report_used_capabilities
kernel_version
compiletime
compiletime
sortkeysiftest
sortvaluesiftest
sortiftest
F_IPV4
F_IPV6
@ -264,6 +268,7 @@ our %EXPORT_TAGS = ( internal => [ qw( create_temp_script
$debug
$file_format
$comment
$test
%config
%origin
@ -793,6 +798,8 @@ our %filecache;
our $compiletime;
our $test;
sub process_shorewallrc($$);
sub add_variables( \% );
#
@ -804,9 +811,12 @@ sub add_variables( \% );
#
# 2. The compiler can run multiple times in the same process so it has to be
# able to re-initialize its dependent modules' state.
#
sub initialize($;$$$) {
( $family, $export, my ( $shorewallrc, $shorewallrc1 ) ) = @_;
####################################################################################################
# Do not change the required part of this prototype unless you want to take on a lot of additional
# work (This function is called from build).
####################################################################################################
sub initialize($;$$$$) {
( $family, $export, $test, my ( $shorewallrc, $shorewallrc1 ) ) = @_;
if ( $family == F_IPV4 ) {
( $product, $Product, $toolname, $toolNAME ) = qw( shorewall Shorewall iptables IPTABLES );
@ -851,7 +861,7 @@ sub initialize($;$$$) {
TC_SCRIPT => '',
EXPORT => 0,
KLUDGEFREE => '',
VERSION => '5.2.0-Beta1',
VERSION => '5.2.4.1',
CAPVERSION => 50200 ,
BLACKLIST_LOG_TAG => '',
RELATED_LOG_TAG => '',
@ -1828,6 +1838,30 @@ sub set_command( $$$ ) {
($command, $doing, $done) = @_;
}
#
# Return the keys or values of the passed hash. If $test, the keys/values will be sorted by their own values
#
sub sortkeysiftest(\%) {
my ( $hashref ) = @_;
return sort keys %$hashref if $test;
return keys %$hashref;
}
sub sortvaluesiftest(\%) {
my ( $hashref ) = @_;
return sort values %$hashref if $test;
return keys %$hashref;
}
#
# Sort a list by the list elements if $test
#
sub sortiftest(@) {
return $test ? sort @_ : @_;
}
#
# Print the current TOD to STDOUT.
#

View File

@ -34,6 +34,7 @@ use Shorewall::Zones;
use Shorewall::Chains qw(:DEFAULT :internal);
use Shorewall::Rules;
use Shorewall::Proc;
use sort 'stable';
use strict;
@ -130,7 +131,7 @@ sub setup_ecn()
}
if ( @hosts ) {
my @interfaces = ( keys %interfaces );
my @interfaces = ( sortkeysiftest %interfaces );
progress_message "$doing ECN control on @interfaces...";
@ -1322,7 +1323,7 @@ sub setup_mac_lists( $ ) {
$maclist_interfaces{ $hostref->[0] } = 1;
}
my @maclist_interfaces = ( keys %maclist_interfaces );
my @maclist_interfaces = ( sortkeysiftest %maclist_interfaces );
if ( $phase == 1 ) {
@ -1408,7 +1409,7 @@ sub setup_mac_lists( $ ) {
#
# Generate jumps from the input and forward chains
#
for my $hostref ( @$maclist_hosts ) {
for my $hostref ( $test ? sort { $a->[0] cmp $b->[0] } @$maclist_hosts : @$maclist_hosts ) {
my $interface = $hostref->[0];
my $ipsec = $hostref->[1];
my @policy = $ipsec && have_ipsec ? ( policy => "--pol $ipsec --dir in" ) : ();
@ -1801,7 +1802,7 @@ sub handle_complex_zone( $$ ) {
my $type = $zoneref->{type};
my $source_ref = ( $zoneref->{hosts}{ipsec} ) || {};
for my $interface ( keys %$source_ref ) {
for my $interface ( sortkeysiftest %$source_ref ) {
my $sourcechainref = $filter_table->{forward_chain $interface};
my @interfacematch;
my $interfaceref = find_interface $interface;
@ -1941,7 +1942,7 @@ sub add_output_jumps( $$$$$$$$ ) {
my $use_output = 0;
my @dest = imatch_dest_net $net;
my @ipsec_out_match = match_ipsec_out $zone , $hostref;
my @zone_interfaces = keys %{zone_interfaces( $zone )};
my @zone_interfaces = sortkeysiftest %{zone_interfaces( $zone )};
if ( @vservers || use_interface_chain( $interface, 'use_output_chain' ) || ( @{$interfacechainref->{rules}} && ! $chain1ref ) || @zone_interfaces > 1 ) {
#
@ -2313,9 +2314,9 @@ sub generate_matrix() {
#
# Take care of PREROUTING, INPUT and OUTPUT jumps
#
for my $type ( keys %$source_hosts_ref ) {
for my $type ( sortkeysiftest %$source_hosts_ref ) {
my $typeref = $source_hosts_ref->{$type};
for my $interface ( keys %$typeref ) {
for my $interface ( sortkeysiftest %$typeref ) {
if ( get_physical( $interface ) eq '+' ) {
#
# Insert the interface-specific jumps before this one which is not interface-specific
@ -2400,9 +2401,9 @@ sub generate_matrix() {
my $chainref = $filter_table->{$chain}; #Will be null if $chain is a Netfilter Built-in target like ACCEPT
for my $type ( keys %{$zone1ref->{hosts}} ) {
for my $type ( sortkeysiftest %{$zone1ref->{hosts}} ) {
my $typeref = $zone1ref->{hosts}{$type};
for my $interface ( keys %$typeref ) {
for my $interface ( sortkeysiftest %$typeref ) {
for my $hostref ( @{$typeref->{$interface}} ) {
next if $hostref->{options}{sourceonly};
if ( $zone ne $zone1 || $num_ifaces > 1 || $hostref->{options}{routeback} ) {

View File

@ -1892,8 +1892,8 @@ sub map_provider_to_interface() {
my $haveoptional;
for my $providerref ( values %providers ) {
if ( $providerref->{optional} ) {
for my $provider ( @providers ) {
if ( ( my $providerref=$providers{$provider} )->{optional} ) {
unless ( $haveoptional++ ) {
emit( 'if [ -n "$interface" ]; then',
' case $interface in' );
@ -2054,8 +2054,7 @@ sub compile_updown() {
);
}
my @nonshared = ( grep $providers{$_}->{optional},
values %provider_interfaces );
my @nonshared = ( grep $providers{$_}->{optional}, sortvaluesiftest %provider_interfaces );
if ( @nonshared ) {
my $interfaces = join( '|', map $providers{$_}->{physical}, @nonshared );
@ -2246,9 +2245,11 @@ sub handle_optional_interfaces() {
# names but they might derive from wildcard interface entries. Optional interfaces which do not have
# wildcard physical names are also included in the providers table.
#
for my $providerref ( grep $_->{optional} , values %providers ) {
push @interfaces, $providerref->{interface};
$wildcards ||= $providerref->{wildcard};
for my $provider ( @providers ) {
if ( ( my $providerref = $providers{$provider} )->{optional} ) {
push @interfaces, $providerref->{interface};
$wildcards ||= $providerref->{wildcard};
}
}
#
@ -2296,17 +2297,7 @@ sub handle_optional_interfaces() {
emit( "$physical)" ), push_indent if $wildcards;
if ( $provider eq $physical ) {
#
# Just an optional interface, or provider and interface are the same
#
emit qq(if [ -z "\$interface" -o "\$interface" = "$physical" ]; then);
} else {
#
# Provider
#
emit qq(if [ -z "\$interface" -o "\$interface" = "$physical" ]; then);
}
emit qq(if [ -z "\$interface" -o "\$interface" = "$physical" ]; then);
push_indent;

View File

@ -155,7 +155,7 @@ sub setup_proxy_arp() {
emit '';
for my $interface ( keys %reset ) {
for my $interface ( sortkeysiftest %reset ) {
unless ( $set{interface} ) {
my $physical = get_physical $interface;
emit ( "if [ -f /proc/sys/net/ipv$family/conf/$physical/$proc_file ]; then" ,
@ -164,7 +164,7 @@ sub setup_proxy_arp() {
}
}
for my $interface ( keys %set ) {
for my $interface ( sortkeysiftest %set ) {
my $physical = get_physical $interface;
emit ( "if [ -f /proc/sys/net/ipv$family/conf/$physical/$proc_file ]; then" ,
" echo 1 > /proc/sys/net/ipv$family/conf/$physical/$proc_file" );

View File

@ -29,6 +29,7 @@ package Shorewall::Zones;
require Exporter;
use Shorewall::Config qw(:DEFAULT :internal);
use Shorewall::IPAddrs;
use sort 'stable';
use strict;
@ -847,10 +848,10 @@ sub dump_zone_contents() {
$entry .= ( " mark=" . in_hex( $zoneref->{mark} ) ) if exists $zoneref->{mark};
if ( $hostref ) {
for my $type ( keys %$hostref ) {
for my $type ( sortkeysiftest %$hostref ) {
my $interfaceref = $hostref->{$type};
for my $interface ( keys %$interfaceref ) {
for my $interface ( sortkeysiftest %$interfaceref ) {
my $iref = $interfaces{$interface};
my $arrayref = $interfaceref->{$interface};
@ -2320,9 +2321,9 @@ sub find_hosts_by_option( $ ) {
}
for my $zone ( grep ! ( $zones{$_}{type} & FIREWALL ) , @zones ) {
for my $type (keys %{$zones{$zone}{hosts}} ) {
for my $type (sortkeysiftest %{$zones{$zone}{hosts}} ) {
my $interfaceref = $zones{$zone}{hosts}->{$type};
for my $interface ( keys %$interfaceref ) {
for my $interface ( sortkeysiftest %$interfaceref ) {
my $arrayref = $interfaceref->{$interface};
for my $host ( @{$arrayref} ) {
my $ipsec = $host->{ipsec};
@ -2350,9 +2351,9 @@ sub find_zone_hosts_by_option( $$ ) {
my @hosts;
unless ( $zones{$zone}{type} & FIREWALL ) {
for my $type (keys %{$zones{$zone}{hosts}} ) {
for my $type (sortkeysiftest %{$zones{$zone}{hosts}} ) {
my $interfaceref = $zones{$zone}{hosts}->{$type};
for my $interface ( keys %$interfaceref ) {
for my $interface ( sortkeysiftest %$interfaceref ) {
my $arrayref = $interfaceref->{$interface};
for my $host ( @{$arrayref} ) {
if ( my $value = $host->{options}{$option} ) {