diff --git a/Shorewall-perl/Shorewall/Tc.pm b/Shorewall-perl/Shorewall/Tc.pm index d56df57af..6f98bbaea 100644 --- a/Shorewall-perl/Shorewall/Tc.pm +++ b/Shorewall-perl/Shorewall/Tc.pm @@ -552,48 +552,51 @@ sub process_tc_filter( $$$$$$ ) { $rule .= "\\\n match u8 $pnumber 0xFF at 9"; } } - - unless ( $port eq '-' ) { - fatal_error "Only TCP, UDP, SCTP and ICMP may specify DEST PORT" - unless $protonumber == TCP || $protonumber == UDP || $protonumber == SCTP || $protonumber == ICMP; - + + unless ( $port eq '-' && $sport eq '-' ) { + # + # In order to be able to access the protocol header, we must create another hash table and link to it. + # + # Create the Table: + # my $tnum = in_hex3 $devref->{tablenumber}++; emit( "run_tc filter add dev $device parent $devref->{number}:0 protocol ip pref 10 handle $tnum: u32 divisor 1" ); + # + # And link to it using the current contents of $rule + # emit( "run_tc $rule 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 + # $rule = "filter add dev $device protocol ip parent $devref->{number}:0 pref 10 u32 ht $tnum:0"; + + unless ( $port 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 ); + 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; - $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"; + $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" - unless $protonumber == TCP || $protonumber == UDP || $protonumber == SCTP; - my $portnumber = in_hex8 validate_port( $protonumber , $sport ); - - if ( $port eq '-' ) { - my $tnum = in_hex3 $devref->{tablenumber}++; - - emit( "run_tc filter add dev $device parent $devref->{number}:0 protocol ip pref 10 handle $tnum: u32 divisor 1" ); - emit( "run_tc $rule link $tnum:0 offset at 0 mask 0x0F00 shift 6 plus 0 eat" ); - - $rule = "filter add dev $device protocol ip parent $devref->{number}:0 pref 10 u32 ht $tnum:0"; + unless ( $sport eq '-' ) { + fatal_error "Only TCP, UDP and SCTP may specify SOURCE PORT" + unless $protonumber == TCP || $protonumber == UDP || $protonumber == SCTP; + my $portnumber = in_hex8 validate_port( $protonumber , $sport ); + + $portnumber =~ s/0x0000/0x/; + $rule .= "\\\n match u32 ${portnumber}0000 0xFFFF0000 at nexthdr+0"; } - - $portnumber =~ s/0x0000/0x/; - $rule .= "\\\n match u32 ${portnumber}0000 0xFFFF0000 at nexthdr+0"; } emit( "run_tc $rule\\" ,