mirror of
https://gitlab.com/shorewall/code.git
synced 2024-11-22 07:33:43 +01:00
Sort specific hash keys and values if -e
- Makes testing output consistent across Perl versions Signed-off-by: Tom Eastep <teastep@shorewall.net>
This commit is contained in:
parent
ed2fa863c3
commit
5e648a9379
@ -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 ) {
|
||||
|
@ -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)
|
||||
|
@ -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.
|
||||
#
|
||||
|
@ -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} ) {
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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" );
|
||||
|
@ -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};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user