Some optimizations in the new rule infrastructure

Signed-off-by: Tom Eastep <teastep@shorewall.net>
This commit is contained in:
Tom Eastep 2011-07-20 15:53:00 -07:00
parent ca655a6f52
commit 32a8b254a0

View File

@ -458,7 +458,8 @@ my %special = ( rule => CONTROL,
jump => TARGET, jump => TARGET,
target => TARGET, target => TARGET,
targetopts => TARGET ); targetopts => TARGET,
);
my %aliases = ( protocol => 'p', my %aliases = ( protocol => 'p',
source => 's', source => 's',
@ -599,7 +600,13 @@ sub decr_cmd_level( $ ) {
} }
# #
# Transform the passed iptables rule into an internal-form hash reference # Transform the passed iptables rule into an internal-form hash reference.
# Most of the compiler has been converted to use the new form natively.
# A few parts, mostly those dealing with expand_rule(), still generate
# iptables command strings which are converted into the new form by
# transform_rule()
#
# First a helper for setting an individual option
# #
sub set_rule_option( $$$ ) { sub set_rule_option( $$$ ) {
my ( $ruleref, $option, $value ) = @_; my ( $ruleref, $option, $value ) = @_;
@ -614,7 +621,7 @@ sub set_rule_option( $$$ ) {
assert( defined $ruleref->{$option} ); assert( defined $ruleref->{$option} );
if ( $special != EXCLUSIVE ) { if ( $special != EXCLUSIVE ) {
if ( $special == UNIQUE ) { if ( $special == UNIQUE ) {
$ruleref->{$option} = $value; assert(0);
} elsif ( $special == MATCH ) { } elsif ( $special == MATCH ) {
$ruleref->{$option} = [ $ruleref->{$option} ] unless reftype $ruleref->{$option}; $ruleref->{$option} = [ $ruleref->{$option} ] unless reftype $ruleref->{$option};
push @{$ruleref->{$option}}, ( reftype $value ? @$value : $value ); push @{$ruleref->{$option}}, ( reftype $value ? @$value : $value );
@ -633,11 +640,7 @@ sub transform_rule( $ ) {
my $simple = 1; my $simple = 1;
$input =~ s/^\s*//; $input =~ s/^\s*//;
#
# This is the first step in converting the compiler to use an intermediate form for rules.
# We parse the iptables input and convert it into a hash. Eventually, the upper levels
# will generate the hash from the outset
#
while ( $input ) { while ( $input ) {
my $option; my $option;
my $invert = ''; my $invert = '';
@ -651,7 +654,7 @@ sub transform_rule( $ ) {
$invert = '!' if $1; $invert = '!' if $1;
my $opt = $option = $2; my $opt = $option = $2;
fatal_error "Unregonized iptables command ($opt}" unless $option = $aliases{$option}; fatal_error "Unrecognized iptables command ($opt}" unless $option = $aliases{$option};
} else { } else {
fatal_error "Unrecognized iptables command string ($input)"; fatal_error "Unrecognized iptables command string ($input)";
} }
@ -691,7 +694,6 @@ sub transform_rule( $ ) {
set_rule_option( $ruleref, $option, $params ) unless $params eq ''; set_rule_option( $ruleref, $option, $params ) unless $params eq '';
} }
$ruleref->{target} ||= '';
$ruleref->{simple} = $simple; $ruleref->{simple} = $simple;
$ruleref; $ruleref;
@ -701,11 +703,7 @@ sub transform_rule( $ ) {
# A couple of small functions for other modules to use to manipulate rules # A couple of small functions for other modules to use to manipulate rules
# #
sub rule_target( $ ) { sub rule_target( $ ) {
my $ruleref = shift; shift->{target};
assert( reftype $ruleref );
$ruleref->{mode} == CAT_MODE ? $ruleref->{target} || '' : '';
} }
sub clear_rule_target( $ ) { sub clear_rule_target( $ ) {
@ -735,7 +733,7 @@ sub set_rule_target( $$$ ) {
# #
# Convert an trule into iptables input # Convert an trule into iptables input
# #
# First, a helper function # First, a helper function that formats a single option
# #
sub format_option( $$ ) { sub format_option( $$ ) {
my ( $option, $value ) = @_; my ( $option, $value ) = @_;
@ -760,8 +758,9 @@ sub format_rule( $$;$ ) {
if ( exists $ruleref->{$_} ) { if ( exists $ruleref->{$_} ) {
my $value = $ruleref->{$_}; my $value = $ruleref->{$_};
if ( length == 1 ) {
$rule .= ' !' if $value =~ s/^! //; $rule .= ' !' if $value =~ s/^! //;
if ( length == 1 ) {
$rule .= join( '' , ' -', $_, ' ', $value ); $rule .= join( '' , ' -', $_, ' ', $value );
} else { } else {
$rule .= join( '' , ' --', $_, ' ', $value ); $rule .= join( '' , ' --', $_, ' ', $value );
@ -852,7 +851,11 @@ sub add_commands ( $$;@ ) {
trace( $chainref, 'T', ++$rulenum, "$_\n" ) for @_; trace( $chainref, 'T', ++$rulenum, "$_\n" ) for @_;
} }
push @{$chainref->{rules}}, { mode => CMD_MODE, cmd => $_ , cmdlevel => $chainref->{cmdlevel} } for @_; push @{$chainref->{rules}}, { mode => CMD_MODE,
cmd => $_ ,
cmdlevel => $chainref->{cmdlevel} ,
target => '', # Insure that all rules have a target
} for @_;
$chainref->{referenced} = 1; $chainref->{referenced} = 1;
} }
@ -1030,7 +1033,7 @@ sub push_matches {
push @{$ruleref->{$option}}, reftype $value ? @$value : $value; push @{$ruleref->{$option}}, reftype $value ? @$value : $value;
} else { } else {
$ruleref->{$option} = $value; $ruleref->{$option} = $value;
$dont_optimize ||= $option =~ /^[piosd]/ && $value =~ /^!/; $dont_optimize ||= $option =~ /^[piosd]$/ && $value =~ /^!/;
} }
} }
@ -1154,7 +1157,7 @@ sub insert_irule( $$$$;@ ) {
$ruleref->{mode} = ( $ruleref->{cmdlevel} = $chainref->{cmdlevel} ) ? CMD_MODE : CAT_MODE; $ruleref->{mode} = ( $ruleref->{cmdlevel} = $chainref->{cmdlevel} ) ? CMD_MODE : CAT_MODE;
if ( $jump ) { if ( $jump ) {
$jump = 'j' unless have_capability 'GOTO_TARGET'; $jump = 'j' if $jump eq 'g' && ! have_capability 'GOTO_TARGET';
( $target, my $targetopts ) = split ' ', $target, 2; ( $target, my $targetopts ) = split ' ', $target, 2;
$ruleref->{jump} = $jump; $ruleref->{jump} = $jump;
$ruleref->{target} = $target; $ruleref->{target} = $target;
@ -1788,11 +1791,10 @@ sub add_ijump( $$$;@ ) {
$toref->{referenced} = 1; $toref->{referenced} = 1;
add_reference $fromref, $toref; add_reference $fromref, $toref;
$jump = 'j' unless have_capability 'GOTO_TARGET'; $jump = 'j' unless have_capability 'GOTO_TARGET';
} else {
$jump = 'j';
}
push_irule ($fromref, $jump => $to, @matches ); push_irule ($fromref, $jump => $to, @matches );
} else {
push_irule( $fromref, 'j' => $to, @matches );
}
} }
sub insert_ijump( $$$$;@ ) { sub insert_ijump( $$$$;@ ) {
@ -1815,9 +1817,14 @@ sub insert_ijump( $$$$;@ ) {
# #
# If the destination is a chain, mark it referenced # If the destination is a chain, mark it referenced
# #
$toref->{referenced} = 1, add_reference $fromref, $toref if $toref; if ( $toref ) {
$toref->{referenced} = 1;
add_reference $fromref, $toref;
$jump = 'j' unless have_capability 'GOTO_TARGET';
insert_irule ($fromref, $jump => $to, $index, @matches ); insert_irule ($fromref, $jump => $to, $index, @matches );
} else {
insert_irule( $fromref, 'j' => $to, $index, @matches );
}
} }
# #
@ -2310,7 +2317,7 @@ sub replace_references( $$$ ) {
my $rule = 0; my $rule = 0;
for ( @{$fromref->{rules}} ) { for ( @{$fromref->{rules}} ) {
$rule++; $rule++;
if ( ( $_->{target} || '' ) eq $name ) { if ( $_->{target} eq $name ) {
$_->{target} = $target; $_->{target} = $target;
$_->{targetopts} = $targetopts if $targetopts; $_->{targetopts} = $targetopts if $targetopts;
@ -2356,7 +2363,7 @@ sub replace_references1( $$ ) {
if ( $fromref->{referenced} ) { if ( $fromref->{referenced} ) {
for ( @{$fromref->{rules}} ) { for ( @{$fromref->{rules}} ) {
$rule++; $rule++;
if ( ( $_->{target} || '' ) eq $name ) { if ( $_->{target} eq $name ) {
# #
# The target is the passed chain -- merge the two rules into one # The target is the passed chain -- merge the two rules into one
# #