forked from extern/shorewall_code
Cruft removal
Signed-off-by: Tom Eastep <teastep@shorewall.net>
This commit is contained in:
parent
8cdc83638e
commit
3ca9577f04
@ -151,6 +151,7 @@ our %EXPORT_TAGS = (
|
|||||||
new_nat_chain
|
new_nat_chain
|
||||||
optimize_chain
|
optimize_chain
|
||||||
check_optimization
|
check_optimization
|
||||||
|
optimize_level0
|
||||||
optimize_ruleset
|
optimize_ruleset
|
||||||
setup_zone_mss
|
setup_zone_mss
|
||||||
newexclusionchain
|
newexclusionchain
|
||||||
@ -200,7 +201,6 @@ our %EXPORT_TAGS = (
|
|||||||
do_ipsec
|
do_ipsec
|
||||||
log_rule
|
log_rule
|
||||||
expand_rule
|
expand_rule
|
||||||
promote_blacklist_rules
|
|
||||||
addnatjump
|
addnatjump
|
||||||
set_chain_variables
|
set_chain_variables
|
||||||
mark_firewall_not_started
|
mark_firewall_not_started
|
||||||
@ -257,7 +257,6 @@ our $VERSION = 'MODULEVERSION';
|
|||||||
# ]
|
# ]
|
||||||
# logchains => { <key1> = <chainref1>, ... }
|
# logchains => { <key1> = <chainref1>, ... }
|
||||||
# references => { <ref1> => <refs>, <ref2> => <refs>, ... }
|
# references => { <ref1> => <refs>, <ref2> => <refs>, ... }
|
||||||
# blacklist => <number of blacklist rules at the head of the rules array> ( 0 or 1 )
|
|
||||||
# blacklistsection
|
# blacklistsection
|
||||||
# => Chain was created by entries in the BLACKLIST section of the rules file
|
# => Chain was created by entries in the BLACKLIST section of the rules file
|
||||||
# action => <action tuple that generated this chain>
|
# action => <action tuple that generated this chain>
|
||||||
@ -1224,9 +1223,7 @@ sub delete_reference( $$ ) {
|
|||||||
# Chain reference , Rule Number, Rule
|
# Chain reference , Rule Number, Rule
|
||||||
#
|
#
|
||||||
# In the first function, the rule number is zero-relative. In the second function,
|
# In the first function, the rule number is zero-relative. In the second function,
|
||||||
# the rule number is one-relative. In the first function, if the rule number is < 0, then
|
# the rule number is one-relative.
|
||||||
# the rule is a jump to a blacklist chain (blacklst or blackout). The rule will be
|
|
||||||
# inserted at the front of the chain and the chain's 'blacklist' member incremented.
|
|
||||||
#
|
#
|
||||||
sub insert_rule1($$$)
|
sub insert_rule1($$$)
|
||||||
{
|
{
|
||||||
@ -1238,11 +1235,6 @@ sub insert_rule1($$$)
|
|||||||
assert( ! ( $ruleref->{cmdlevel} = $chainref->{cmdlevel}) );
|
assert( ! ( $ruleref->{cmdlevel} = $chainref->{cmdlevel}) );
|
||||||
$ruleref->{mode} = CAT_MODE;
|
$ruleref->{mode} = CAT_MODE;
|
||||||
|
|
||||||
if ( $number < 0 ) {
|
|
||||||
$chainref->{blacklist}++;
|
|
||||||
$number = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
splice( @{$chainref->{rules}}, $number, 0, $ruleref );
|
splice( @{$chainref->{rules}}, $number, 0, $ruleref );
|
||||||
|
|
||||||
trace( $chainref, 'I', ++$number, $ruleref ) if $debug;
|
trace( $chainref, 'I', ++$number, $ruleref ) if $debug;
|
||||||
@ -1283,11 +1275,6 @@ sub insert_irule( $$$$;@ ) {
|
|||||||
$ruleref->{comment} = $comment unless $ruleref->{comment};
|
$ruleref->{comment} = $comment unless $ruleref->{comment};
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( $number < 0 ) {
|
|
||||||
$chainref->{blacklist}++;
|
|
||||||
$number = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
splice( @{$chainref->{rules}}, $number, 0, $ruleref );
|
splice( @{$chainref->{rules}}, $number, 0, $ruleref );
|
||||||
|
|
||||||
trace( $chainref, 'I', ++$number, format_rule( $chainref, $ruleref ) ) if $debug;
|
trace( $chainref, 'I', ++$number, format_rule( $chainref, $ruleref ) ) if $debug;
|
||||||
@ -1315,13 +1302,12 @@ sub clone_rule( $ ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Do final work to 'delete' a chain. We leave it in the chain table but clear
|
# Do final work to 'delete' a chain. We leave it in the chain table but clear
|
||||||
# the 'referenced', 'rules', 'references' and 'blacklist' members.
|
# the 'referenced', 'rules', and 'references' members.
|
||||||
#
|
#
|
||||||
sub delete_chain( $ ) {
|
sub delete_chain( $ ) {
|
||||||
my $chainref = shift;
|
my $chainref = shift;
|
||||||
|
|
||||||
$chainref->{referenced} = 0;
|
$chainref->{referenced} = 0;
|
||||||
$chainref->{blacklist} = 0;
|
|
||||||
$chainref->{rules} = [];
|
$chainref->{rules} = [];
|
||||||
$chainref->{references} = {};
|
$chainref->{references} = {};
|
||||||
trace( $chainref, 'X', undef, '' ) if $debug;
|
trace( $chainref, 'X', undef, '' ) if $debug;
|
||||||
@ -1391,7 +1377,7 @@ sub decrement_reference_count( $$ ) {
|
|||||||
#
|
#
|
||||||
# The rules generated by interface options are added to the interfaces's input chain and
|
# The rules generated by interface options are added to the interfaces's input chain and
|
||||||
# forward chain. Shorewall::Rules::generate_matrix() may decide to move those rules to
|
# forward chain. Shorewall::Rules::generate_matrix() may decide to move those rules to
|
||||||
# the head of a rules chain (behind any blacklist rule already there).
|
# the head of a rules chain.
|
||||||
#
|
#
|
||||||
sub move_rules( $$ ) {
|
sub move_rules( $$ ) {
|
||||||
my ($chain1, $chain2 ) = @_;
|
my ($chain1, $chain2 ) = @_;
|
||||||
@ -1402,15 +1388,12 @@ sub move_rules( $$ ) {
|
|||||||
my $rules = $chain2->{rules};
|
my $rules = $chain2->{rules};
|
||||||
my $count = @{$chain1->{rules}};
|
my $count = @{$chain1->{rules}};
|
||||||
my $tableref = $chain_table{$chain1->{table}};
|
my $tableref = $chain_table{$chain1->{table}};
|
||||||
my $blacklist = $chain2->{blacklist};
|
|
||||||
my $filtered;
|
my $filtered;
|
||||||
my $filtered1 = $chain1->{filtered};
|
my $filtered1 = $chain1->{filtered};
|
||||||
my $filtered2 = $chain2->{filtered};
|
my $filtered2 = $chain2->{filtered};
|
||||||
my @filtered1;
|
my @filtered1;
|
||||||
my @filtered2;
|
my @filtered2;
|
||||||
my $rule;
|
my $rule;
|
||||||
|
|
||||||
assert( ! $chain1->{blacklist} );
|
|
||||||
#
|
#
|
||||||
# We allow '+' in chain names and '+' is an RE meta-character. Escape it.
|
# We allow '+' in chain names and '+' is an RE meta-character. Escape it.
|
||||||
#
|
#
|
||||||
@ -1430,11 +1413,11 @@ sub move_rules( $$ ) {
|
|||||||
push @filtered2 , shift @{$chain2->{rules}} while $filtered--;
|
push @filtered2 , shift @{$chain2->{rules}} while $filtered--;
|
||||||
|
|
||||||
if ( $debug ) {
|
if ( $debug ) {
|
||||||
my $rule = $blacklist + $filtered2;
|
my $rule = $filtered2;
|
||||||
trace( $chain2, 'A', ++$rule, $_ ) for @{$chain1->{rules}};
|
trace( $chain2, 'A', ++$rule, $_ ) for @{$chain1->{rules}};
|
||||||
}
|
}
|
||||||
|
|
||||||
splice @$rules, $blacklist, 0, @{$chain1->{rules}};
|
unshift @$rules, @{$chain1->{rules}};
|
||||||
|
|
||||||
$chain2->{referenced} = 1;
|
$chain2->{referenced} = 1;
|
||||||
|
|
||||||
@ -1442,16 +1425,9 @@ sub move_rules( $$ ) {
|
|||||||
# In a firewall->x policy chain, multiple DHCP ACCEPT rules can be moved to the head of the chain.
|
# In a firewall->x policy chain, multiple DHCP ACCEPT rules can be moved to the head of the chain.
|
||||||
# This hack avoids that.
|
# This hack avoids that.
|
||||||
#
|
#
|
||||||
if ( $blacklist ) {
|
shift @{$rules} while @{$rules} > 1 && $rules->[0]{dhcp} && $rules->[1]{dhcp};
|
||||||
my $rule = shift @{$rules};
|
|
||||||
shift @{$rules} while @{$rules} > 1 && $rules->[0]{dhcp} && $rules->[1]{dhcp};
|
|
||||||
unshift @{$rules}, $rule;
|
|
||||||
} else {
|
|
||||||
shift @{$rules} while @{$rules} > 1 && $rules->[0]{dhcp} && $rules->[1]{dhcp};
|
|
||||||
}
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Now insert the filter rules at the head of the chain (before blacklist rules)
|
# Now insert the filter rules at the head of the chain
|
||||||
#
|
#
|
||||||
|
|
||||||
if ( $filtered1 ) {
|
if ( $filtered1 ) {
|
||||||
@ -1495,8 +1471,6 @@ sub copy_rules( $$;$ ) {
|
|||||||
my $name1 = $chain1->{name};
|
my $name1 = $chain1->{name};
|
||||||
my $name = $name1;
|
my $name = $name1;
|
||||||
my $name2 = $chain2->{name};
|
my $name2 = $chain2->{name};
|
||||||
my $blacklist1 = $chain1->{blacklist};
|
|
||||||
my $blacklist2 = $chain2->{blacklist};
|
|
||||||
my @rules1 = @{$chain1->{rules}};
|
my @rules1 = @{$chain1->{rules}};
|
||||||
my $rules2 = $chain2->{rules};
|
my $rules2 = $chain2->{rules};
|
||||||
my $count = @{$chain1->{rules}};
|
my $count = @{$chain1->{rules}};
|
||||||
@ -1505,22 +1479,6 @@ sub copy_rules( $$;$ ) {
|
|||||||
# We allow '+' in chain names and '+' is an RE meta-character. Escape it.
|
# We allow '+' in chain names and '+' is an RE meta-character. Escape it.
|
||||||
#
|
#
|
||||||
pop @$rules2 unless $nojump; # Delete the jump to chain1
|
pop @$rules2 unless $nojump; # Delete the jump to chain1
|
||||||
|
|
||||||
if ( $blacklist2 && $blacklist1 ) {
|
|
||||||
#
|
|
||||||
# Chains2 already has a blacklist jump -- delete the one at the head of chain1's rule list
|
|
||||||
#
|
|
||||||
my $rule = shift @rules1;
|
|
||||||
|
|
||||||
my $chainb = $rule->{target};
|
|
||||||
|
|
||||||
assert( $chainb =~ /^black/ );
|
|
||||||
|
|
||||||
delete_reference $chain1, $chainb;
|
|
||||||
|
|
||||||
assert( ! --$chain1->{blacklist} );
|
|
||||||
$blacklist1 = 0;
|
|
||||||
}
|
|
||||||
#
|
#
|
||||||
# Chain2 is now a referent of all of Chain1's targets
|
# Chain2 is now a referent of all of Chain1's targets
|
||||||
#
|
#
|
||||||
@ -1528,17 +1486,6 @@ sub copy_rules( $$;$ ) {
|
|||||||
increment_reference_count( $tableref->{$_->{target}}, $name2 ) if $_->{target};
|
increment_reference_count( $tableref->{$_->{target}}, $name2 ) if $_->{target};
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( $blacklist1 ) {
|
|
||||||
assert( $blacklist1 == 1 );
|
|
||||||
|
|
||||||
trace( $chain2, 'A', 1 , $rules1[0]) if $debug;
|
|
||||||
|
|
||||||
unshift @$rules2, shift @rules1;
|
|
||||||
|
|
||||||
$chain1->{blacklist} = 0;
|
|
||||||
$chain2->{blacklist} = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( $debug ) {
|
if ( $debug ) {
|
||||||
my $rule = @$rules2;
|
my $rule = @$rules2;
|
||||||
trace( $chain2, 'A', ++$rule, $_ ) for @rules1;
|
trace( $chain2, 'A', ++$rule, $_ ) for @rules1;
|
||||||
@ -1879,7 +1826,6 @@ sub new_chain($$)
|
|||||||
log => 1,
|
log => 1,
|
||||||
cmdlevel => 0,
|
cmdlevel => 0,
|
||||||
references => {},
|
references => {},
|
||||||
blacklist => 0,
|
|
||||||
filtered => 0
|
filtered => 0
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2680,6 +2626,25 @@ sub check_optimization( $ ) {
|
|||||||
#
|
#
|
||||||
# Perform Optimization
|
# Perform Optimization
|
||||||
#
|
#
|
||||||
|
# When an unreferenced chain is found, itis deleted unless its 'dont_delete' flag is set.
|
||||||
|
sub optimize_level0() {
|
||||||
|
for my $table ( qw/raw rawpost mangle nat filter/ ) {
|
||||||
|
next if $family == F_IPV6 && $table eq 'nat';
|
||||||
|
my $tableref = $chain_table{$table};
|
||||||
|
my @chains = grep $_->{referenced}, values %$tableref;
|
||||||
|
my $chains = @chains;
|
||||||
|
|
||||||
|
for my $chainref ( @chains ) {
|
||||||
|
#
|
||||||
|
# If the chain isn't branched to, then delete it
|
||||||
|
#
|
||||||
|
unless ( $chainref->{dont_delete} || keys %{$chainref->{references}} ) {
|
||||||
|
delete_chain $chainref if $chainref->{referenced};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sub optimize_level4( $$ ) {
|
sub optimize_level4( $$ ) {
|
||||||
my ( $table, $tableref ) = @_;
|
my ( $table, $tableref ) = @_;
|
||||||
my $progress = 1;
|
my $progress = 1;
|
||||||
@ -2687,7 +2652,6 @@ sub optimize_level4( $$ ) {
|
|||||||
#
|
#
|
||||||
# Make repeated passes through each table looking for short chains (those with less than 2 entries)
|
# Make repeated passes through each table looking for short chains (those with less than 2 entries)
|
||||||
#
|
#
|
||||||
# When an unreferenced chain is found, itis deleted unless its 'dont_delete' flag is set.
|
|
||||||
# When an empty chain is found, delete the references to it.
|
# When an empty chain is found, delete the references to it.
|
||||||
# When a chain with a single entry is found, replace it's references by its contents
|
# When a chain with a single entry is found, replace it's references by its contents
|
||||||
#
|
#
|
||||||
@ -5828,59 +5792,6 @@ sub expand_rule( $$$$$$$$$$;$ )
|
|||||||
$diface;
|
$diface;
|
||||||
}
|
}
|
||||||
|
|
||||||
#
|
|
||||||
# Where a zone sharing a multi-zone interface has an 'in' blacklist rule, move the rule to the beginning of
|
|
||||||
# the associated interface chain
|
|
||||||
#
|
|
||||||
sub promote_blacklist_rules() {
|
|
||||||
my $chainbref = $filter_table->{blacklst};
|
|
||||||
|
|
||||||
return 1 unless $chainbref;
|
|
||||||
|
|
||||||
my $promoted = 1;
|
|
||||||
|
|
||||||
while ( $promoted ) {
|
|
||||||
$promoted = 0;
|
|
||||||
#
|
|
||||||
# Copy 'blacklst''s references since they will change in the following loop
|
|
||||||
#
|
|
||||||
my @references = map $filter_table->{$_}, keys %{$chainbref->{references}};
|
|
||||||
|
|
||||||
for my $chain1ref ( @references ) {
|
|
||||||
assert( $chain1ref->{blacklist} == 1 );
|
|
||||||
|
|
||||||
my $copied = 0;
|
|
||||||
my $rule = $chain1ref->{rules}[0];
|
|
||||||
my $chain1 = $chain1ref->{name};
|
|
||||||
|
|
||||||
for my $chain2ref ( map $filter_table->{$_}, keys %{$chain1ref->{references}} ) {
|
|
||||||
unless ( $chain2ref->{builtin} ) {
|
|
||||||
#
|
|
||||||
# This is not INPUT or FORWARD -- we wouldn't want to move the
|
|
||||||
# rule to the head of one of those chains
|
|
||||||
$copied++;
|
|
||||||
#
|
|
||||||
# Copy the blacklist rule to the head of the parent chain (after any
|
|
||||||
# filter rules) unless it already has a blacklist rule.
|
|
||||||
#
|
|
||||||
unless ( $chain2ref->{blacklist} ) {
|
|
||||||
splice @{$chain2ref->{rules}}, $chain2ref->{filtered}, 0, $rule;
|
|
||||||
add_reference $chain2ref, $chainbref;
|
|
||||||
$chain2ref->{blacklist} = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( $copied ) {
|
|
||||||
shift @{$chain1ref->{rules}};
|
|
||||||
$chain1ref->{blacklist} = 0;
|
|
||||||
delete_reference $chain1ref, $chainbref;
|
|
||||||
$promoted = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# The following code generates the input to iptables-restore from the contents of the
|
# The following code generates the input to iptables-restore from the contents of the
|
||||||
# @rules arrays in the chain table entries.
|
# @rules arrays in the chain table entries.
|
||||||
|
@ -814,6 +814,8 @@ sub compiler {
|
|||||||
#
|
#
|
||||||
generate_matrix;
|
generate_matrix;
|
||||||
|
|
||||||
|
optimize_level0;
|
||||||
|
|
||||||
if ( $config{OPTIMIZE} & 0x1E ) {
|
if ( $config{OPTIMIZE} & 0x1E ) {
|
||||||
progress_message2 'Optimizing Ruleset...';
|
progress_message2 'Optimizing Ruleset...';
|
||||||
#
|
#
|
||||||
@ -883,6 +885,8 @@ sub compiler {
|
|||||||
#
|
#
|
||||||
generate_matrix;
|
generate_matrix;
|
||||||
|
|
||||||
|
optimize_level0;
|
||||||
|
|
||||||
if ( $config{OPTIMIZE} & 0x1E ) {
|
if ( $config{OPTIMIZE} & 0x1E ) {
|
||||||
progress_message2 'Optimizing Ruleset...';
|
progress_message2 'Optimizing Ruleset...';
|
||||||
#
|
#
|
||||||
|
@ -560,7 +560,6 @@ sub add_common_rules ( $ ) {
|
|||||||
add_rule_pair dont_delete( new_standard_chain( 'logdrop' ) ), '' , 'DROP' , $level ;
|
add_rule_pair dont_delete( new_standard_chain( 'logdrop' ) ), '' , 'DROP' , $level ;
|
||||||
add_rule_pair dont_delete( new_standard_chain( 'logreject' ) ), '' , 'reject' , $level ;
|
add_rule_pair dont_delete( new_standard_chain( 'logreject' ) ), '' , 'reject' , $level ;
|
||||||
$dynamicref = dont_optimize( new_standard_chain( 'dynamic' ) );
|
$dynamicref = dont_optimize( new_standard_chain( 'dynamic' ) );
|
||||||
add_ijump $filter_table->{INPUT}, j => $dynamicref, @state;
|
|
||||||
add_commands( $dynamicref, '[ -f ${VARDIR}/.dynamic ] && cat ${VARDIR}/.dynamic >&3' );
|
add_commands( $dynamicref, '[ -f ${VARDIR}/.dynamic ] && cat ${VARDIR}/.dynamic >&3' );
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -647,8 +646,8 @@ sub add_common_rules ( $ ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for ( option_chains( $interface ) ) {
|
for ( option_chains( $interface ) ) {
|
||||||
add_ijump( $filter_table->{$_}, j => 'ACCEPT', state_imatch $faststate ) if $config{FASTACCEPT};
|
|
||||||
add_ijump( $filter_table->{$_}, j => $dynamicref, @state ) if $dynamicref;
|
add_ijump( $filter_table->{$_}, j => $dynamicref, @state ) if $dynamicref;
|
||||||
|
add_ijump( $filter_table->{$_}, j => 'ACCEPT', state_imatch $faststate ) if $config{FASTACCEPT};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -787,7 +786,7 @@ sub add_common_rules ( $ ) {
|
|||||||
'dhcp',
|
'dhcp',
|
||||||
1 ) for input_option_chain( $interface ), output_chain( $interface );
|
1 ) for input_option_chain( $interface ), output_chain( $interface );
|
||||||
|
|
||||||
add_ijump( $filter_table->{forward_chain $interface} ,
|
add_ijump( $filter_table->{forward_option_chain $interface} ,
|
||||||
j => 'ACCEPT',
|
j => 'ACCEPT',
|
||||||
p => "udp --dport $ports" ,
|
p => "udp --dport $ports" ,
|
||||||
imatch_dest_dev( $interface ) )
|
imatch_dest_dev( $interface ) )
|
||||||
|
@ -2632,15 +2632,27 @@ sub process_rules() {
|
|||||||
my $chainref = $filter_table->{rules_chain( $zone1, $zone2 )};
|
my $chainref = $filter_table->{rules_chain( $zone1, $zone2 )};
|
||||||
|
|
||||||
if ( zone_type( $zone2 ) & (FIREWALL | VSERVER ) ) {
|
if ( zone_type( $zone2 ) & (FIREWALL | VSERVER ) ) {
|
||||||
for my $interface ( @interfaces ) {
|
if ( @interfaces ==1 ) {
|
||||||
if ( my $chain1ref = $filter_table->{input_option_chain $interface} ) {
|
if ( my $chain1ref = $filter_table->{input_option_chain $interfaces[0]} ) {
|
||||||
add_ijump ( $chainref , j => $chain1ref->{name}, @interfaces > 1 ? imatch_source_dev( $interface ) : () );
|
push( @{$chainref->{rules}}, @{$chain1ref->{rules}} );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for my $interface ( @interfaces ) {
|
||||||
|
if ( my $chain1ref = $filter_table->{input_option_chain $interface} ) {
|
||||||
|
add_ijump ( $chainref , j => $chain1ref->{name}, imatch_source_dev( $interface ) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for my $interface ( @interfaces ) {
|
if ( @interfaces ==1 ) {
|
||||||
if ( my $chain1ref = $filter_table->{forward_option_chain $interface} ) {
|
if ( my $chain1ref = $filter_table->{forward_option_chain $interfaces[0]} ) {
|
||||||
add_ijump ( $chainref , j => $chain1ref->{name}, @interfaces > 1 ? imatch_source_dev( $interface ) : () );
|
push( @{$chainref->{rules}}, @{$chain1ref->{rules}} );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for my $interface ( @interfaces ) {
|
||||||
|
if ( my $chain1ref = $filter_table->{forward_option_chain $interface} ) {
|
||||||
|
add_ijump ( $chainref , j => $chain1ref->{name}, imatch_source_dev( $interface ) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user