Support port lists in tcfilters file

git-svn-id: https://shorewall.svn.sourceforge.net/svnroot/shorewall/trunk@8321 fbd18981-670d-0410-9b5c-8dc0c1a9a2bb
This commit is contained in:
teastep 2008-03-21 14:59:14 +00:00
parent 2c10a936f5
commit dc17a6976d
2 changed files with 67 additions and 47 deletions

View File

@ -252,19 +252,21 @@ New Features in 4.1.6.
Protocol Name/Number. Specify "-" if any PROTO should Protocol Name/Number. Specify "-" if any PROTO should
match. match.
DEST PORT DEST PORT(S)
Destination port. May only be given if the PROTO is A comma-separated list of destination ports. May only
tcp, udp or sctp. Neither port ranges nor port lists be given if the PROTO is tcp, udp, icmp or
may be given. Specify "-" if any PORT should match. sctp. Port ranges may not be used. Specify "-"
if any PORT should match.
SOURCE PORT SOURCE PORT(S)
Source port. May only be given if the PROTO is A comma-separated list of source port. May only be
tcp, udp or sctp. Neither port ranges nor port lists given if the PROTO is tcp, udp or sctp. Port ranges
may be given. Specify "-" if any PORT should match. may not be used. Specify "-" if any PORT should match.
Entries in /etc/shorewall/tcfilters generate U32 tc filters which Entries in /etc/shorewall/tcfilters generate U32 tc filters which
may be displayed using the "shorewall show tc" ("shorewall-lite may be displayed using the "shorewall show filters" ("shorewall-lite
show tc") command. show filters") command. Note: The 'show filters' command is an
alias for the existing 'show classifiers' command.
Note that /etc/shorewall/tcfilters provides a usable alternative to Note that /etc/shorewall/tcfilters provides a usable alternative to
HIGH_ROUTE_MARKS=Yes. You can use marks to select between providers HIGH_ROUTE_MARKS=Yes. You can use marks to select between providers

View File

@ -125,7 +125,7 @@ our @deferred_rules;
# tablenumber => <next u32 table to be allocated for this device> # tablenumber => <next u32 table to be allocated for this device>
# default => <default class mark value> # default => <default class mark value>
# redirected => [ <dev1>, <dev2>, ... ] # redirected => [ <dev1>, <dev2>, ... ]
# u32tables => [ table1 , ... ] } # }
# #
our @tcdevices; our @tcdevices;
our %tcdevices; our %tcdevices;
@ -524,7 +524,7 @@ sub validate_tc_class( $$$$$$ ) {
# Process a record from the tcfilters file # Process a record from the tcfilters file
# #
sub process_tc_filter( $$$$$$ ) { sub process_tc_filter( $$$$$$ ) {
my ($devclass , $source, $dest , $proto, $port , $sport ) = @_; my ($devclass , $source, $dest , $proto, $portlist , $sportlist ) = @_;
my ($device, $class, $rest ) = split /:/, $devclass, 3; my ($device, $class, $rest ) = split /:/, $devclass, 3;
@ -564,60 +564,78 @@ sub process_tc_filter( $$$$$$ ) {
} }
} }
unless ( $port eq '-' && $sport eq '-' ) { if ( $portlist eq '-' && $sportlist eq '-' ) {
emit( "\nrun_tc $rule\\" ,
" flowid $devref->{number}:$class" ,
'' );
} else {
# #
# In order to be able to access the protocol header, we must create another hash table and link to it. # In order to be able to access the protocol header, we must create another hash table and link to it.
# #
# Create the Table if we don't already have a table for this device and protocol. # Create the Table.
# #
my $tnum = $devref->{u32tables}[$protonumber]; my $tnum = in_hex3 $devref->{tablenumber}++;
unless ( defined $tnum ) { emit( "\nrun_tc filter add dev $device parent $devnum:0 protocol ip pref 10 handle $tnum: u32 divisor 1" );
$tnum = $devref->{u32tables}[$protonumber] = in_hex3 $devref->{tablenumber}++;
emit( "run_tc filter add dev $device parent $devnum:0 protocol ip pref 10 handle $tnum: u32 divisor 1" );
}
# #
# And link to it using the current contents of $rule # And link to it using the current contents of $rule
# #
emit( "run_tc $rule\\" , emit( "\nrun_tc $rule\\" ,
" link $tnum:0 offset at 0 mask 0x0F00 shift 6 plus 0 eat" ); " link $tnum:0 offset at 0 mask 0x0F00 shift 6 plus 0 eat" );
# #
# The rule to match the port(s) will be inserted into the new table # The rule to match the port(s) will be inserted into the new table
# #
$rule = "filter add dev $device protocol ip parent $devnum:0 pref 10 u32 ht $tnum:0"; $rule = "filter add dev $device protocol ip parent $devnum:0 pref 10 u32 ht $tnum:0";
unless ( $port eq '-' ) { if ( $portlist eq '-' ) {
fatal_error "Only TCP, UDP, SCTP and ICMP may specify DEST PORT"
unless $protonumber == TCP || $protonumber == UDP || $protonumber == SCTP || $protonumber == ICMP;
if ( $protonumber == ICMP ) {
my ( $icmptype , $icmpcode ) = split '//', validate_icmp( $port );
$icmptype = in_hex2 numeric_value $icmptype;
$icmpcode = in_hex2 numeric_value $icmpcode if defined $icmpcode;
$rule .= "\\\n match u8 $icmptype 0xff at nexthdr+0";
$rule .= "\\\n match u8 $icmpcode 0xff at nexthdr+1" if defined $icmpcode;
} else {
my $portnumber = in_hex8 validate_port( $protonumber , $port );
$rule .= "\\\n match u32 $portnumber 0x0000ffff at nexthdr+0";
}
}
unless ( $sport eq '-' ) {
fatal_error "Only TCP, UDP and SCTP may specify SOURCE PORT" fatal_error "Only TCP, UDP and SCTP may specify SOURCE PORT"
unless $protonumber == TCP || $protonumber == UDP || $protonumber == SCTP; unless $protonumber == TCP || $protonumber == UDP || $protonumber == SCTP;
my $portnumber = in_hex4 validate_port( $protonumber , $sport ); for my $sport ( split_list $sportlist , 'port list' ) {
my $portnumber = in_hex4 validate_port( $protonumber , $sport );
$rule .= "\\\n match u32 ${portnumber}0000 0xffff0000 at nexthdr+0"; emit( "\nrun_tc $rule\\" ,
" match u32 ${portnumber}0000 0xffff0000 at nexthdr+0\\" ,
" flowid $devref->{number}:$class" );
}
} else {
fatal_error "Only TCP, UDP, SCTP and ICMP may specify DEST PORT"
unless $protonumber == TCP || $protonumber == UDP || $protonumber == SCTP || $protonumber == ICMP;
for my $port( split_list $portlist, 'port list' ) {
if ( $protonumber == ICMP ) {
fatal_error "Only TCP, UDP and SCTP may specify SOURCE PORT" if $sportlist ne '-';
my ( $icmptype , $icmpcode ) = split '//', validate_icmp( $port );
$icmptype = in_hex2 numeric_value $icmptype;
$icmpcode = in_hex2 numeric_value $icmpcode if defined $icmpcode;
my $rule1 = " match u8 $icmptype 0xff at nexthdr+0";
$rule1 .= "\\\n match u8 $icmpcode 0xff at nexthdr+1" if defined $icmpcode;
emit( "\nrun_tc ${rule}\\" ,
"$rule1\\" ,
" flowid $devref->{number}:$class" );
} else {
my $portnumber = in_hex8 validate_port( $protonumber , $port );
my $rule1 = "match u32 $portnumber 0x0000ffff at nexthdr+0";
if ( $sportlist eq '-' ) {
emit( "\nrun_tc ${rule}\\" ,
" $rule1\\" ,
" flowid $devref->{number}:$class" );
} else {
for my $sport ( split_list $sportlist , 'port list' ) {
my $portnumber = in_hex4 validate_port( $protonumber , $sport );
emit( "\nrun_tc ${rule}\\",
" $rule1\\" ,
" match u32 ${portnumber}0000 0xffff0000 at nexthdr+0\\" ,
" flowid $devref->{number}:$class" );
}
}
}
}
} }
} }
emit( "run_tc $rule\\" , emit '';
" flowid $devref->{number}:$class" ,
'' );
progress_message " TC Filter \"$currentline\" $done"; progress_message " TC Filter \"$currentline\" $done";