Implement ipset matches in tcfilters

Signed-off-by: Tom Eastep <teastep@shorewall.net>
This commit is contained in:
Tom Eastep 2014-01-03 09:35:34 -08:00
parent 78ecf9bdc8
commit 7e1a310929
2 changed files with 71 additions and 7 deletions

View File

@ -374,6 +374,7 @@ our %capdesc = ( NAT_ENABLED => 'NAT',
CONDITION_MATCH => 'Condition Match',
IPTABLES_S => 'iptables -S',
BASIC_FILTER => 'Basic Filter',
BASIC_EMATCH => 'Basic Filter ematch',
CT_TARGET => 'CT Target',
STATISTIC_MATCH =>
'Statistics Match',
@ -953,6 +954,7 @@ sub initialize( $;$$) {
CONDITION_MATCH => undef,
IPTABLES_S => undef,
BASIC_FILTER => undef,
BASIC_EMATCH => undef,
CT_TARGET => undef,
STATISTIC_MATCH => undef,
IMQ_TARGET => undef,
@ -4270,6 +4272,10 @@ sub Basic_Filter() {
$tc && system( "$tc filter add basic help 2>&1 | grep -q ^Usage" ) == 0;
}
sub Basic_Ematch() {
$tc && have_capability 'BASIC_FILTER' && system( "$tc filter add basic help 2>&1 | egrep -q match" ) == 0;
}
sub Fwmark_Rt_Mask() {
$ip && system( "$ip rule add help 2>&1 | grep -q /MASK" ) == 0;
}
@ -4372,6 +4378,7 @@ our %detect_capability =
AUDIT_TARGET => \&Audit_Target,
ADDRTYPE => \&Addrtype,
BASIC_FILTER => \&Basic_Filter,
BASIC_EMATCH => \&Basic_Ematch,
CHECKSUM_TARGET => \&Checksum_Target,
CLASSIFY_TARGET => \&Classify_Target,
CONDITION_MATCH => \&Condition_Match,
@ -4585,6 +4592,7 @@ sub determine_capabilities() {
$capabilities{CONDITION_MATCH} = detect_capability( 'CONDITION_MATCH' );
$capabilities{IPTABLES_S} = detect_capability( 'IPTABLES_S' );
$capabilities{BASIC_FILTER} = detect_capability( 'BASIC_FILTER' );
$capabilities{BASIC_EMATCH} = detect_capability( 'BASIC_EMATCH' );
$capabilities{CT_TARGET} = detect_capability( 'CT_TARGET' );
$capabilities{STATISTIC_MATCH} = detect_capability( 'STATISTIC_MATCH' );
$capabilities{IMQ_TARGET} = detect_capability( 'IMQ_TARGET' );

View File

@ -1908,6 +1908,36 @@ sub validate_tc_class( ) {
my %validlengths = ( 32 => '0xffe0', 64 => '0xffc0', 128 => '0xff80', 256 => '0xff00', 512 => '0xfe00', 1024 => '0xfc00', 2048 => '0xf800', 4096 => '0xf000', 8192 => '0xe000' );
#
# Handle an ipset name in the SOURCE or DEST columns of a filter
#
sub handle_ematch( $$ ) {
my ( $setname, $option ) = @_;
my $options = $option;
require_capability 'BASIC_EMATCH', 'IPSets', '';
if ( $setname =~ /^(.*)\[([1-6])\]$/ ) {
$setname = $1;
my $count = $2;
$options .= ",$option" while --$count > 0;
} elsif ( $setname =~ /^(.*)\[((?:src|dst)(?:,(?:src|dst))){0,5}\]$/ ) {
$setname = $1;
$options = $2 if supplied $2;
my @options = split /,/, $options;
if ( $config{IPSET_WARNINGS} ) {
my %typemap = ( src => 'Source', dst => 'Destination' );
warning_message( "The '$options[0]' ipset flag is used in a $typemap{$option} column" ), unless $options[0] eq $option;
}
}
return " ipset( $setname, $options )";
}
#
# Process a record from the tcfilters file
#
@ -1925,6 +1955,8 @@ sub process_tc_filter1( $$$$$$$$$ ) {
my $devref;
my $ematch = '';
if ( $device =~ /^[\da-fA-F]+$/ && ! $tcdevices{$device} ) {
( $device, $devref ) = dev_by_number( hex_value( $device ) );
} else {
@ -1970,16 +2002,28 @@ sub process_tc_filter1( $$$$$$$$$ ) {
my $rule = "filter add dev $devref->{physical} protocol $ip parent $devnum:0 prio $prio u32";
if ( $source ne '-' ) {
if ( $source =~ /^\+/ ) {
$ematch = join( ' ', 'match', handle_ematch( $source, 'src' ) );
} else {
my ( $net , $mask ) = decompose_net( $source );
$rule .= "\\\n match $ip32 src $net/$mask";
$have_rule = 1;
}
}
if ( $dest ne '-' ) {
if ( $dest =~ /^\+/ ) {
if ( $ematch ) {
$ematch = join( ' ', $ematch, handle_ematch( $dest, 'dst' ) );
} else {
$ematch = join( ' ', 'match', handle_ematch( $dest, 'dst' ) );
}
} else {
my ( $net , $mask ) = decompose_net( $dest );
$rule .= "\\\n match $ip32 dst $net/$mask";
$have_rule = 1;
}
}
if ( $tos ne '-' ) {
my $tosval = $tosoptions{$tos};
@ -2019,13 +2063,25 @@ sub process_tc_filter1( $$$$$$$$$ ) {
}
}
if ( $ematch ) {
if ( $have_rule ) {
my $tnum = in_hex3 $devref->{tablenumber}++;
push @$filtersref, ( "\nrun_tc $rule\\" ,
" link $tnum:0" );
$rule = "filter add dev $devref->{physical} protocol $ip parent $devnum:0 prio $prio basic ht $tnum:0 match ${ematch}";
} else {
$rule = "filter add dev $devref->{physical} protocol $ip parent $devnum:0 prio $prio basic match$ ${ematch}";
$have_rule = 1;
}
}
if ( $portlist eq '-' && $sportlist eq '-' ) {
if ( $have_rule ) {
push @$filtersref , ( "\nrun_tc $rule\\" ,
" flowid $devnum:$class" ,
'' );
} else {
warning_message "Degenerate tcfilter ignored";
warning_message "Degenerate tcfilter ignored" unless $ematch;
}
} else {
fatal_error "Ports may not be specified without a PROTO" unless $protonumber;