mirror of
https://gitlab.com/shorewall/code.git
synced 2024-12-17 20:01:09 +01:00
01c4e3022d
git-svn-id: https://shorewall.svn.sourceforge.net/svnroot/shorewall/trunk@5533 fbd18981-670d-0410-9b5c-8dc0c1a9a2bb
226 lines
5.1 KiB
Perl
226 lines
5.1 KiB
Perl
package Shorewall::Tc;
|
|
require Exporter;
|
|
use Shorewall::Common;
|
|
use Shorewall::Config;
|
|
use Shorewall::Zones;
|
|
use Shorewall::Chains;
|
|
|
|
use strict;
|
|
|
|
our @ISA = qw(Exporter);
|
|
our @EXPORT = qw( process_tcrules );
|
|
our @EXPORT_OK = qw( process_tc_rule );
|
|
our @VERSION = 1.00;
|
|
|
|
my %tcs = ( t => { chain => 'tcpost',
|
|
connmark => 0,
|
|
fw => 1
|
|
} ,
|
|
ct => { chain => 'tcpost' ,
|
|
target => 'CONNMARK --set-mark' ,
|
|
connmark => 1 ,
|
|
fw => 1
|
|
} ,
|
|
c => { target => 'CONNMARK --set-mark' ,
|
|
connmark => 1 ,
|
|
fw => 1
|
|
} ,
|
|
p => { chain => 'tcpre' ,
|
|
connmark => 0 ,
|
|
fw => 0
|
|
} ,
|
|
cp => { chain => 'tcpre' ,
|
|
target => 'CONNMARK --set-mark' ,
|
|
connmark => 1 ,
|
|
fw => 0
|
|
} ,
|
|
f => { chain => 'tcfor' ,
|
|
connmark => 0 ,
|
|
fw => 0
|
|
} ,
|
|
cf => { chain => 'tcfor' ,
|
|
fw => 0 ,
|
|
connmark => 1 ,
|
|
} ,
|
|
t => { chain => 'tcpost' ,
|
|
connmark => 0 ,
|
|
fw => 0
|
|
} ,
|
|
ct => { chain => 'tcpost' ,
|
|
target => 'CONNMARK --set-mark' ,
|
|
connmark => 1 ,
|
|
fw => 0
|
|
} ,
|
|
c => { target => 'CONNMARK --set-mark' ,
|
|
connmark => 1 ,
|
|
fw => 0
|
|
}
|
|
);
|
|
|
|
use constant { NOMARK => 0 ,
|
|
SMALLMARK => 1 ,
|
|
HIGHMARK => 2
|
|
};
|
|
|
|
my @tccmd = ( { pattern => 'SAVE' ,
|
|
target => 'CONNMARK --save-mark --mask' ,
|
|
mark => SMALLMARK ,
|
|
mask => '0xFF'
|
|
} ,
|
|
{ pattern => 'RESTORE' ,
|
|
target => 'CONNMARK --restore-mark --mask' ,
|
|
mark => SMALLMARK ,
|
|
mask => '0xFF'
|
|
} ,
|
|
{ pattern => 'CONTINUE',
|
|
target => 'RETURN' ,
|
|
mark => NOMARK ,
|
|
mask => ''
|
|
} ,
|
|
{ pattern => '\|.*' ,
|
|
target => 'MARK --or-mark' ,
|
|
mark => HIGHMARK ,
|
|
mask => '' } ,
|
|
{ pattern => '&.*' ,
|
|
target => 'MARK --and-mark ' ,
|
|
mark => HIGHMARK ,
|
|
mask => ''
|
|
}
|
|
);
|
|
|
|
sub process_tc_rule( $$$$$$$$$$ ) {
|
|
my ( $mark, $source, $dest, $proto, $ports, $sports, $user, $testval, $length, $tos , $extra ) = @_;
|
|
|
|
my $original_mark = $mark;
|
|
|
|
( $mark, my $designator ) = split /:/, $mark;
|
|
|
|
my $chain = $env{MARKING_CHAIN};
|
|
my $target = 'MARK --set-mark';
|
|
my $tcsref;
|
|
my $connmark = 0;
|
|
my $classid = 0;
|
|
|
|
if ( $source ) {
|
|
if ( $source eq $firewall_zone ) {
|
|
$chain = 'tcout';
|
|
$source = '';
|
|
} else {
|
|
$chain = 'tcout' if $source =~ s/^($firewall_zone)://;
|
|
}
|
|
}
|
|
|
|
if ( $designator ) {
|
|
$tcsref = $tcs{$designator};
|
|
|
|
if ( $tcsref ) {
|
|
if ( $chain eq 'tcout' ) {
|
|
fatal_error "Invalid chain designator for source $firewall_zone; rule \"$line\"" unless $tcsref->{fw};
|
|
}
|
|
|
|
$chain = $tcsref->{chain} if $tcsref->{chain};
|
|
$target = $tcsref->{target} if $tcsref->{target};
|
|
$mark = "$mark/0xFF" if $connmark = $tcsref->{connmark};
|
|
|
|
} else {
|
|
fatal_error "Invalid MARK ($original_mark) in rule \"$line\"" unless $mark =~ /^([0-9]+|0x[0-9a-f]+)$/ and $designator =~ /^([0-9]+|0x[0-9a-f]+)$/;
|
|
$chain = 'tcpost';
|
|
$classid = 1;
|
|
$mark = $original_mark;
|
|
$target = 'CLASSIFY --set-class';
|
|
}
|
|
}
|
|
|
|
my $mask = 0xffff;
|
|
|
|
my ($cmd, $rest) = split '/', $mark;
|
|
|
|
unless ( $classid )
|
|
{
|
|
MARK:
|
|
{
|
|
PATTERN:
|
|
for my $tccmd ( @tccmd ) {
|
|
if ( $cmd =~ /^($tccmd->{pattern})$/ ) {
|
|
fatal_error "$mark not valid with :C[FP]" if $connmark;
|
|
|
|
$target = "$tccmd->{target} ";
|
|
my $marktype = $tccmd->{mark};
|
|
|
|
$mark =~ s/^[!&]//;
|
|
|
|
if ( $rest ) {
|
|
fatal_error "Invalid MARK ($original_mark)" if $marktype == NOMARK;
|
|
|
|
$mark = $rest if $tccmd->{mask};
|
|
|
|
if ( $marktype == SMALLMARK ) {
|
|
verify_small_mark $mark;
|
|
} else {
|
|
validate_mark $mark;
|
|
}
|
|
} elsif ( $tccmd->{mask} ) {
|
|
$mark = $tccmd->{mask};
|
|
}
|
|
|
|
last MARK;
|
|
}
|
|
}
|
|
}
|
|
|
|
validate_mark $mark;
|
|
|
|
fatal_error 'Marks < 256 may not be set in the PREROUTING chain when HIGH_ROUTE_MARKS=Yes'
|
|
if $cmd || $chain eq 'tcpre' || numeric_value( $cmd ) <= 0xFF || $config{HIGH_ROUTE_MARKS};
|
|
}
|
|
|
|
expand_rule
|
|
ensure_chain( 'mangle' , $chain ) ,
|
|
do_proto( $proto, $ports, $sports) . do_test( $testval, $mask ) ,
|
|
$source ,
|
|
$dest ,
|
|
'' ,
|
|
"-j $target $mark" ,
|
|
'' ,
|
|
'' ,
|
|
'';
|
|
|
|
progress_message " TC Rule \"$line\" $done";
|
|
|
|
}
|
|
|
|
#
|
|
# Process the tcrules file
|
|
#
|
|
sub process_tcrules() {
|
|
|
|
open TC, "$ENV{TMP_DIR}/tcrules" or fatal_error "Unable to open stripped tcrules file: $!";
|
|
|
|
while ( $line = <TC> ) {
|
|
|
|
chomp $line;
|
|
$line =~ s/\s+/ /g;
|
|
|
|
my ( $mark, $source, $dest, $proto, $ports, $sports, $user, $testval, $length, $tos , $extra ) = split /\s+/, $line;
|
|
|
|
if ( $mark eq 'COMMENT' ) {
|
|
if ( $capabilities{COMMENTS} ) {
|
|
( $comment = $line ) =~ s/^\s*COMMENT\s*//;
|
|
$comment =~ s/\s*$//;
|
|
} else {
|
|
warning_message "COMMENT ignored -- requires comment support in iptables/Netfilter";
|
|
}
|
|
} else {
|
|
fatal_error "Invalid tcrule: \"$line\"" if $extra;
|
|
process_tc_rule $mark, $source, $dest, $proto, $ports, $sports, $user, $testval, $length, $tos
|
|
}
|
|
|
|
}
|
|
|
|
close TC;
|
|
|
|
$comment = '';
|
|
}
|
|
|
|
1;
|