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 # 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 # Address Family
@ -619,6 +619,7 @@ our %opttype = ( rule => CONTROL,
mode => CONTROL, mode => CONTROL,
cmdlevel => CONTROL, cmdlevel => CONTROL,
simple => CONTROL, simple => CONTROL,
matches => CONTROL,
i => UNIQUE, i => UNIQUE,
s => UNIQUE, s => UNIQUE,
@ -634,6 +635,8 @@ our %opttype = ( rule => CONTROL,
policy => MATCH, policy => MATCH,
state => EXCLUSIVE, state => EXCLUSIVE,
'conntrack --ctstate' =>
EXCLUSIVE,
conntrack => COMPLEX, conntrack => COMPLEX,
@ -831,12 +834,13 @@ sub set_rule_option( $$$ ) {
} }
} else { } else {
$ruleref->{$option} = $value; $ruleref->{$option} = $value;
push @{$ruleref->{matches}}, $option;
} }
} }
sub transform_rule( $;\$ ) { sub transform_rule( $;\$ ) {
my ( $input, $completeref ) = @_; my ( $input, $completeref ) = @_;
my $ruleref = { mode => CAT_MODE, target => '' }; my $ruleref = { mode => CAT_MODE, matches => [], target => '' };
my $simple = 1; my $simple = 1;
my $target = ''; my $target = '';
my $jump = ''; my $jump = '';
@ -950,11 +954,17 @@ sub format_option( $$ ) {
$rule; $rule;
} }
sub debug() {
return 1;
}
sub format_rule( $$;$ ) { sub format_rule( $$;$ ) {
my ( $chainref, $ruleref, $suppresshdr ) = @_; my ( $chainref, $ruleref, $suppresshdr ) = @_;
return $ruleref->{cmd} if exists $ruleref->{cmd}; return $ruleref->{cmd} if exists $ruleref->{cmd};
debug if $chainref->{name} eq 'drct-net';
my $rule = $suppresshdr ? '' : "-A $chainref->{name}"; my $rule = $suppresshdr ? '' : "-A $chainref->{name}";
for ( @unique_options ) { 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( '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} ) { if ( $ruleref->{target} ) {
$rule .= join( ' ', " -$ruleref->{jump}", $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}; 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}; set_rule_option( $toref, 'policy', $fromref->{policy} ) if exists $fromref->{policy};
unless ( $toref->{comment} ) { unless ( $toref->{comment} ) {
@ -1302,6 +1327,7 @@ sub push_matches {
} else { } else {
$ruleref->{$option} = $value; $ruleref->{$option} = $value;
$dont_optimize ||= $option =~ /^[piosd]$/ && $value =~ /^!/; $dont_optimize ||= $option =~ /^[piosd]$/ && $value =~ /^!/;
push @{$ruleref->{matches}}, $option;
} }
} }
@ -1313,7 +1339,7 @@ sub push_irule( $$$;@ ) {
( $target, my $targetopts ) = split ' ', $target, 2; ( $target, my $targetopts ) = split ' ', $target, 2;
my $ruleref = {}; my $ruleref = { matches => [] };
$ruleref->{mode} = ( $ruleref->{cmdlevel} = $chainref->{cmdlevel} ) ? CMD_MODE : CAT_MODE; $ruleref->{mode} = ( $ruleref->{cmdlevel} = $chainref->{cmdlevel} ) ? CMD_MODE : CAT_MODE;
@ -1476,8 +1502,13 @@ sub clone_rule( $ ) {
my $newruleref = {}; my $newruleref = {};
while ( my ( $key, $value ) = each %$oldruleref ) { while ( my ( $key, $value ) = each %$oldruleref ) {
if ( reftype $value ) {
my @array = @$value;
$newruleref->{$key} = \@array;
} else {
$newruleref->{$key} = $value; $newruleref->{$key} = $value;
} }
}
$newruleref; $newruleref;
} }
@ -3548,6 +3579,20 @@ sub combine_dports {
$baseref->{'multiport'} = '--dports ' . join( ',' , @ports ); $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; $baseref->{comment} = $comment if $comment;
trace ( $chainref, 'R', $basenum, $baseref ) if $debug; trace ( $chainref, 'R', $basenum, $baseref ) if $debug;

View File

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

View File

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