Order matches in rules.

Signed-off-by: Tom Eastep <teastep@shorewall.net>
This commit is contained in:
Tom Eastep 2013-04-12 11:37:29 -07:00
parent 6950cd2576
commit 0da38cc38e
3 changed files with 74 additions and 34 deletions

View File

@ -513,7 +513,7 @@ our $mode;
#
# A reference to this rule is returned when we try to push a rule onto a 'complete' chain
#
our $dummyrule = { simple => 1, mode => CAT_MODE };
our $dummyrule = { simple => 1, matches => [], mode => CAT_MODE };
#
# Address Family
@ -619,6 +619,7 @@ our %opttype = ( rule => CONTROL,
mode => CONTROL,
cmdlevel => CONTROL,
simple => CONTROL,
matches => CONTROL,
i => UNIQUE,
s => UNIQUE,
@ -634,6 +635,8 @@ our %opttype = ( rule => CONTROL,
policy => MATCH,
state => EXCLUSIVE,
'conntrack --ctstate' =>
EXCLUSIVE,
conntrack => COMPLEX,
@ -831,12 +834,13 @@ sub set_rule_option( $$$ ) {
}
} else {
$ruleref->{$option} = $value;
push @{$ruleref->{matches}}, $option;
}
}
sub transform_rule( $;\$ ) {
my ( $input, $completeref ) = @_;
my $ruleref = { mode => CAT_MODE, target => '' };
my $ruleref = { mode => CAT_MODE, matches => [], target => '' };
my $simple = 1;
my $target = '';
my $jump = '';
@ -950,11 +954,17 @@ sub format_option( $$ ) {
$rule;
}
sub debug() {
return 1;
}
sub format_rule( $$;$ ) {
my ( $chainref, $ruleref, $suppresshdr ) = @_;
return $ruleref->{cmd} if exists $ruleref->{cmd};
debug if $chainref->{name} eq 'drct-net';
my $rule = $suppresshdr ? '' : "-A $chainref->{name}";
for ( @unique_options ) {
@ -971,10 +981,19 @@ sub format_rule( $$;$ ) {
}
}
$rule .= format_option( 'state', $ruleref->{state} ) if defined $ruleref->{state};
$rule .= format_option( 'policy', $ruleref->{policy} ) if defined $ruleref->{policy};
$rule .= format_option( $_, $ruleref->{$_} ) for sort ( grep ! $opttype{$_}, keys %{$ruleref} );
if ( defined ( my $state = $ruleref->{'conntrack --ctstate'} ) ) {
$rule .= format_option( 'conntrack --ctstate' , $state );
} elsif ( defined $ruleref->{state} ) {
$rule .= format_option( 'state', $ruleref->{state} );
}
my %done;
for ( grep ! $opttype{$_}, @{$ruleref->{matches}} ) {
$rule .= format_option( $_, $ruleref->{$_} ) unless $done{$_}++;
}
if ( $ruleref->{target} ) {
$rule .= join( ' ', " -$ruleref->{jump}", $ruleref->{target} );
@ -1041,6 +1060,12 @@ sub merge_rules( $$$ ) {
set_rule_option ( $toref, 'state', $fromref->{state} ) if $fromref->{state};
}
unless ( $toref->{'conntrack --ctstate'} ) {
set_rule_option( $toref,
'conntrack --ctstate',
$fromref->{'conntrack --ctstate'} ) if $fromref->{'conntrack --ctstate'};
}
set_rule_option( $toref, 'policy', $fromref->{policy} ) if exists $fromref->{policy};
unless ( $toref->{comment} ) {
@ -1302,6 +1327,7 @@ sub push_matches {
} else {
$ruleref->{$option} = $value;
$dont_optimize ||= $option =~ /^[piosd]$/ && $value =~ /^!/;
push @{$ruleref->{matches}}, $option;
}
}
@ -1313,7 +1339,7 @@ sub push_irule( $$$;@ ) {
( $target, my $targetopts ) = split ' ', $target, 2;
my $ruleref = {};
my $ruleref = { matches => [] };
$ruleref->{mode} = ( $ruleref->{cmdlevel} = $chainref->{cmdlevel} ) ? CMD_MODE : CAT_MODE;
@ -1476,7 +1502,12 @@ sub clone_rule( $ ) {
my $newruleref = {};
while ( my ( $key, $value ) = each %$oldruleref ) {
$newruleref->{$key} = $value;
if ( reftype $value ) {
my @array = @$value;
$newruleref->{$key} = \@array;
} else {
$newruleref->{$key} = $value;
}
}
$newruleref;
@ -3548,6 +3579,20 @@ sub combine_dports {
$baseref->{'multiport'} = '--dports ' . join( ',' , @ports );
}
my @matches = @{$baseref->{matches}};
$baseref->{matches} = [];
my $switched = 0;
for ( @matches ) {
if ( $_ eq 'dport' || $_ eq 'sport' ) {
push @{$baseref->{matches}}, 'multiport' unless $switched++;
} else {
push @{$baseref->{matches}}, $_;
}
}
$baseref->{comment} = $comment if $comment;
trace ( $chainref, 'R', $basenum, $baseref ) if $debug;

View File

@ -1965,12 +1965,14 @@ sub handle_stickiness( $ ) {
$rule2 = clone_rule( $_ );
clear_rule_target( $rule2 );
set_rule_option( $rule2, 'mark', "--mark 0/$mask -m recent --name $list --remove" );
set_rule_option( $rule2, 'mark', "--mark 0\/$mask" );
set_rule_option( $rule2, 'recent', "--name $list --remove" );
} else {
$rule1 = clone_rule( $_ );
clear_rule_target( $rule1 );
set_rule_option( $rule1, 'mark', "--mark $mark\/$mask -m recent --name $list --set" );
set_rule_option( $rule1, 'mark', "--mark $mark\/$mask" );
set_rule_option( $rule1, 'recent', "--name $list --set" );
$rule2 = '';
}
@ -1990,32 +1992,22 @@ sub handle_stickiness( $ ) {
for my $chainref ( $stickoref, $setstickoref ) {
if ( $chainref->{name} eq 'sticko' ) {
$rule1 = {};
while ( my ( $key, $value ) = each %$_ ) {
$rule1->{$key} = $value;
}
$rule1 = clone_rule $_;
set_rule_target( $rule1, 'MARK', "--set-mark $mark" );
set_rule_option( $rule1, 'recent', " --name $list --rdest --update --seconds 300" );
$rule2 = {};
while ( my ( $key, $value ) = each %$_ ) {
$rule2->{$key} = $value;
}
$rule2 = clone_rule $_;
clear_rule_target( $rule2 );
set_rule_option ( $rule2, 'mark', "--mark 0\/$mask -m recent --name $list --rdest --remove" );
set_rule_option ( $rule2, 'mark', "--mark 0\/$mask" );
set_rule_option ( $rule2, 'recent', "--name $list --rdest --remove" );
} else {
$rule1 = {};
while ( my ( $key, $value ) = each %$_ ) {
$rule1->{$key} = $value;
}
$rule1 = clone_rule $_;
clear_rule_target( $rule1 );
set_rule_option ( $rule1, 'mark', "--mark $mark -m recent --name $list --rdest --set" );
set_rule_option ( $rule1, 'mark', "--mark $mark" );
set_rule_option ( $rule1, 'recent', "--name $list --rdest --set" );
$rule2 = '';
}

View File

@ -2080,8 +2080,9 @@ sub process_rule ( $$$$$$$$$$$$$$$$$$$ ) {
my $inchain = ''; # Set to true when a chain reference is passed.
my $normalized_target;
my $normalized_action;
my $blacklist = ( $section == BLACKLIST_SECTION );
my $matches = $rule;
my $blacklist = ( $section == BLACKLIST_SECTION );
my $matches = $rule;
my $raw_matches = '';
if ( $inchain = defined $chainref ) {
( $inaction, undef, undef, undef ) = split /:/, $normalized_action = $chainref->{action}, 4 if $chainref->{action};
@ -2093,13 +2094,13 @@ sub process_rule ( $$$$$$$$$$$$$$$$$$$ ) {
my $inline_matches = get_inline_matches;
if ( $inline_matches =~ /^(.*\s+)-j\s+(.+)$/ ) {
$matches .= $1;
$raw_matches .= $1;
$action = $2;
my ( $target ) = split ' ', $action;
fatal_error "Unknown jump target ($action)" unless $targets{$target};
fatal_error "INLINE may not have a parameter when '-j' is specified in the free-form area" if $param ne '';
} else {
$matches .= "$inline_matches ";
$raw_matches .= "$inline_matches ";
if ( $param eq '' ) {
$action = $loglevel ? 'LOG' : '';
@ -2109,8 +2110,6 @@ sub process_rule ( $$$$$$$$$$$$$$$$$$$ ) {
$param = '' unless defined $param;
}
}
$rule = $matches;
}
#
# Determine the validity of the action
@ -2133,7 +2132,7 @@ sub process_rule ( $$$$$$$$$$$$$$$$$$$ ) {
my $generated = process_macro( $basictarget,
$chainref,
$rule,
$rule . $raw_matches,
$target,
$current_param,
$source,
@ -2477,7 +2476,7 @@ sub process_rule ( $$$$$$$$$$$$$$$$$$$ ) {
my $generated = process_inline( $basictarget,
$chainref,
$rule,
$rule . $raw_matches,
$loglevel,
$target,
$current_param,
@ -2519,6 +2518,7 @@ sub process_rule ( $$$$$$$$$$$$$$$$$$$ ) {
do_time( $time ) ,
do_headers( $headers ) ,
do_condition( $condition , $chain ) ,
$raw_matches ,
);
} elsif ( $section & ( ESTABLISHED_SECTION | INVALID_SECTION | RELATED_SECTION | UNTRACKED_SECTION ) ) {
$rule .= join( '',
@ -2531,6 +2531,7 @@ sub process_rule ( $$$$$$$$$$$$$$$$$$$ ) {
do_headers( $headers ) ,
do_condition( $condition , $chain ) ,
do_helper( $helper ) ,
$raw_matches ,
);
} else {
$rule .= join( '',
@ -2542,6 +2543,7 @@ sub process_rule ( $$$$$$$$$$$$$$$$$$$ ) {
do_time( $time ) ,
do_headers( $headers ) ,
do_condition( $condition , $chain ) ,
$raw_matches ,
);
}
@ -2615,7 +2617,8 @@ sub process_rule ( $$$$$$$$$$$$$$$$$$$ ) {
do_ratelimit( $ratelimit, 'ACCEPT' ),
do_user $user,
do_test( $mark , $globals{TC_MASK} ),
do_condition( $condition , $chain )
do_condition( $condition , $chain ),
$raw_matches,
);
$loglevel = '';
$action = 'ACCEPT';