Allow port ranges in /etc/shorewall/tcfilters

git-svn-id: https://shorewall.svn.sourceforge.net/svnroot/shorewall/trunk@8323 fbd18981-670d-0410-9b5c-8dc0c1a9a2bb
This commit is contained in:
teastep 2008-03-21 17:08:55 +00:00
parent 19ea03b36d
commit 9b048e836e
4 changed files with 78 additions and 33 deletions

View File

@ -255,13 +255,14 @@ New Features in 4.1.6.
DEST PORT(S) DEST PORT(S)
A comma-separated list of destination ports. May only A comma-separated list of destination ports. May only
be given if the PROTO is tcp, udp, icmp or be given if the PROTO is tcp, udp, icmp or
sctp. Port ranges may not be used. Specify "-" sctp. Port ranges may be used, except with the PROTO is
if any PORT should match. icmp. Specify "-" if any PORT should match.
SOURCE PORT(S) SOURCE PORT(S)
A comma-separated list of source port. May only be A comma-separated list of source port. May only be
given if the PROTO is tcp, udp or sctp. Port ranges given if the PROTO is tcp, udp or sctp. Port ranges
may not be used. Specify "-" if any PORT should match. may be used unless the protocol is icmp. 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 filters" ("shorewall-lite may be displayed using the "shorewall show filters" ("shorewall-lite

View File

@ -43,6 +43,7 @@ our @EXPORT = qw( ALLIPv4
validate_host validate_host
validate_range validate_range
ip_range_explicit ip_range_explicit
expand_port_range
allipv4 allipv4
rfc1918_neworks rfc1918_neworks
resolve_proto resolve_proto
@ -355,4 +356,36 @@ sub validate_icmp( $ ) {
fatal_error "Invalid ICMP Type ($type)" fatal_error "Invalid ICMP Type ($type)"
} }
sub expand_port_range( $$ ) {
my ( $proto, $range ) = @_;
my ( $first, $last ) = split /:/, $range, 2;
if ( defined $last ) {
my @result;
( $first , $last ) = ( validate_port( $proto, $first ) , validate_port( $proto, $last ) );
while ( $first <= $last ) {
my $mask = 0xffff;
my $y = 2;
my $z = 1;
while ( ( $first % $y ) == 0 && ( $first + $y ) < $last ) {
$mask <<= 1;
$z = $y;
$y <<= 1;
}
push @result, sprintf( '%04x', $first ) , sprintf( '%04x' , $mask & 0xffff );
$first += $z;
}
fatal_error "Invalid port range ($range)" unless @result;
@result;
} else {
( sprintf( '%04x' , validate_port( $proto, $first ) ) , 'ffff' );
}
}
1; 1;

View File

@ -591,20 +591,23 @@ sub process_tc_filter( $$$$$$ ) {
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;
for my $sport ( split_list $sportlist , 'port list' ) { for my $sportrange ( split_list $sportlist , 'port list' ) {
my $portnumber = in_hex4 validate_port( $protonumber , $sport ); my @sportlist = expand_port_range $protonumber , $sportrange;
while ( @sportlist ) {
my ( $sport, $smask ) = ( shift @sportlist, shift @sportlist );
emit( "\nrun_tc $rule\\" , emit( "\nrun_tc $rule\\" ,
" match u32 ${portnumber}0000 0xffff0000 at nexthdr+0\\" , " match u32 0x${sport}0000 0x${smask}0000 at nexthdr+0\\" ,
" flowid $devref->{number}:$class" ); " flowid $devref->{number}:$class" );
} }
}
} else { } else {
fatal_error "Only TCP, UDP, SCTP and ICMP may specify DEST PORT" fatal_error "Only TCP, UDP, SCTP and ICMP may specify DEST PORT"
unless $protonumber == TCP || $protonumber == UDP || $protonumber == SCTP || $protonumber == ICMP; unless $protonumber == TCP || $protonumber == UDP || $protonumber == SCTP || $protonumber == ICMP;
for my $port( split_list $portlist, 'port list' ) { for my $portrange ( split_list $portlist, 'port list' ) {
if ( $protonumber == ICMP ) { if ( $protonumber == ICMP ) {
fatal_error "Only TCP, UDP and SCTP may specify SOURCE PORT" if $sportlist ne '-'; my ( $icmptype , $icmpcode ) = split '//', validate_icmp( $portrange );
my ( $icmptype , $icmpcode ) = split '//', validate_icmp( $port );
$icmptype = in_hex2 numeric_value $icmptype; $icmptype = in_hex2 numeric_value $icmptype;
$icmpcode = in_hex2 numeric_value $icmpcode if defined $icmpcode; $icmpcode = in_hex2 numeric_value $icmpcode if defined $icmpcode;
@ -615,18 +618,27 @@ sub process_tc_filter( $$$$$$ ) {
"$rule1\\" , "$rule1\\" ,
" flowid $devref->{number}:$class" ); " flowid $devref->{number}:$class" );
} else { } else {
my $portnumber = in_hex8 validate_port( $protonumber , $port ); my @portlist = expand_port_range $protonumber , $portrange;
my $rule1 = "match u32 $portnumber 0x0000ffff at nexthdr+0";
while ( @portlist ) {
my ( $port, $mask ) = ( shift @portlist, shift @portlist );
my $rule1 = "match u32 0x0000${port} 0x0000${mask} at nexthdr+0";
if ( $sportlist eq '-' ) { if ( $sportlist eq '-' ) {
emit( "\nrun_tc ${rule}\\" , emit( "\nrun_tc ${rule}\\" ,
" $rule1\\" , " $rule1\\" ,
" flowid $devref->{number}:$class" ); " flowid $devref->{number}:$class" );
} else { } else {
for my $sport ( split_list $sportlist , 'port list' ) { for my $sportrange ( split_list $sportlist , 'port list' ) {
my $portnumber = in_hex4 validate_port( $protonumber , $sport ); my @sportlist = expand_port_range $protonumber , $sportrange;
while ( @sportlist ) {
my ( $sport, $smask ) = ( shift @sportlist, shift @sportlist );
emit( "\nrun_tc ${rule}\\", emit( "\nrun_tc ${rule}\\",
" $rule1\\" , " $rule1\\" ,
" match u32 ${portnumber}0000 0xffff0000 at nexthdr+0\\" , " match u32 0x${sport}0000 0x${smask}0000 at nexthdr+0\\" ,
" flowid $devref->{number}:$class" ); " flowid $devref->{number}:$class" );
} }
} }
@ -634,6 +646,8 @@ sub process_tc_filter( $$$$$$ ) {
} }
} }
} }
}
}
emit ''; emit '';

View File

@ -1179,10 +1179,6 @@ ip link set ifb0 up</command></programlisting>
<para>ipsets are not supported</para> <para>ipsets are not supported</para>
</listitem> </listitem>
<listitem>
<para>port ranges are not supported</para>
</listitem>
<listitem> <listitem>
<para>DNS Names are not supported</para> <para>DNS Names are not supported</para>
</listitem> </listitem>
@ -1278,8 +1274,8 @@ eth0 192.168.1.0/24 206.124.146.179</programlisting></para>
<listitem> <listitem>
<para>Comma-separated list of destination port names or numbers. <para>Comma-separated list of destination port names or numbers.
May only be specified if the protocol is TCP, UDP, SCTP or May only be specified if the protocol is TCP, UDP, SCTP or ICMP.
ICMP.</para> Port ranges are supported except for ICMP.</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
@ -1288,7 +1284,8 @@ eth0 192.168.1.0/24 206.124.146.179</programlisting></para>
<listitem> <listitem>
<para>Comma-separated list of source port names or numbers. May <para>Comma-separated list of source port names or numbers. May
only be specified if the protocol is TCP, UDP or SCTP.</para> only be specified if the protocol is TCP, UDP or SCTP. Port ranges
are supported.</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
</variablelist> </variablelist>