196
196
sub process_tc_rule( ) {
197
my ( $originalmark, $source, $dest, $proto, $ports, $sports, $user, $testval, $length, $tos , $connbytes, $helper, $headers, $probability );
197
my ( $originalmark, $source, $dest, $proto, $ports, $sports, $user, $testval, $length, $tos , $connbytes, $helper, $headers, $probability , $dscp );
198
198
if ( $family == F_IPV4 ) {
199
( $originalmark, $source, $dest, $proto, $ports, $sports, $user, $testval, $length, $tos , $connbytes, $helper, $probability ) =
200
split_line1 'tcrules file', { mark => 0, source => 1, dest => 2, proto => 3, dport => 4, sport => 5, user => 6, test => 7, length => 8, tos => 9, connbytes => 10, helper => 11, probability => 12 };
199
( $originalmark, $source, $dest, $proto, $ports, $sports, $user, $testval, $length, $tos , $connbytes, $helper, $probability, $dscp ) =
200
split_line1 'tcrules file', { mark => 0, source => 1, dest => 2, proto => 3, dport => 4, sport => 5, user => 6, test => 7, length => 8, tos => 9, connbytes => 10, helper => 11, probability => 12 , dscp => 13 };
203
( $originalmark, $source, $dest, $proto, $ports, $sports, $user, $testval, $length, $tos , $connbytes, $helper, $headers, $probability ) =
204
split_line1 'tcrules file', { mark => 0, source => 1, dest => 2, proto => 3, dport => 4, sport => 5, user => 6, test => 7, length => 8, tos => 9, connbytes => 10, helper => 11, headers => 12, probability => 13 };
203
( $originalmark, $source, $dest, $proto, $ports, $sports, $user, $testval, $length, $tos , $connbytes, $helper, $headers, $probability, $dscp ) =
204
split_line1 'tcrules file', { mark => 0, source => 1, dest => 2, proto => 3, dport => 4, sport => 5, user => 6, test => 7, length => 8, tos => 9, connbytes => 10, helper => 11, headers => 12, probability => 13 , dscp => 14 };
240
240
my $fw = firewall_zone;
246
my %processtcc = ( sticky => sub() {
247
if ( $chain eq 'tcout' ) {
250
fatal_error "SAME rules are only allowed in the PREROUTING and OUTPUT chains" if $chain ne 'tcpre';
253
$restriction = DESTIFACE_DISALLOW;
255
ensure_mangle_chain($target);
260
my ( $srcdst, $mask1, $mask2, $shift ) = ('src', 255, 0, 0 );
262
require_capability 'IPMARK_TARGET', 'IPMARK', 's';
264
if ( $cmd =~ /^IPMARK\((.+?)\)$/ ) {
268
my ( $sd, $m1, $m2, $s , $bad ) = split ',', $params;
270
fatal_error "Invalid IPMARK parameters ($params)" if $bad;
271
fatal_error "Invalid IPMARK parameter ($sd)" unless ( $sd eq 'src' || $sd eq 'dst' );
274
if ( supplied $m1 ) {
275
$val = numeric_value ($m1);
276
fatal_error "Invalid Mask ($m1)" unless defined $val && $val && $val <= 0xffffffff;
277
$mask1 = in_hex ( $val & 0xffffffff );
280
if ( supplied $m2 ) {
281
$val = numeric_value ($m2);
282
fatal_error "Invalid Mask ($m2)" unless defined $val && $val <= 0xffffffff;
283
$mask2 = in_hex ( $val & 0xffffffff );
287
$val = numeric_value ($s);
288
fatal_error "Invalid Shift Bits ($s)" unless defined $val && $val >= 0 && $val < 128;
292
fatal_error "Invalid MARK/CLASSIFY ($cmd)" unless $cmd eq 'IPMARK';
295
$target = "IPMARK --addr $srcdst --and-mask $mask1 --or-mask $mask2 --shift $shift";
298
require_capability( 'TPROXY_TARGET', 'Use of TPROXY', 's');
300
fatal_error "Invalid TPROXY specification( $cmd/$rest )" if $rest;
304
$cmd =~ /TPROXY\((.+?)\)$/;
308
fatal_error "Invalid TPROXY specification( $cmd )" unless defined $params;
310
( $mark, my $port, my $ip, my $bad ) = split ',', $params;
312
fatal_error "Invalid TPROXY specification( $cmd )" if defined $bad;
315
$port = validate_port( 'tcp', $port );
320
$target .= " --on-port $port";
322
if ( supplied $ip ) {
323
if ( $family == F_IPV6 ) {
324
$ip = $1 if $ip =~ /^\[(.+)\]$/ || $ip =~ /^<(.+)>$/;
327
validate_address $ip, 1;
328
$target .= " --on-ip $ip";
331
$target .= ' --tproxy-mark';
334
fatal_error "TTL is not supported in IPv6 - use HL instead" if $family == F_IPV6;
335
fatal_error "Invalid TTL specification( $cmd/$rest )" if $rest;
336
fatal_error "Chain designator $designator not allowed with TTL" if $designator && ! ( $designator eq 'F' );
340
$cmd =~ /^TTL\(([-+]?\d+)\)$/;
344
fatal_error "Invalid TTL specification( $cmd )" unless $param && ( $param = abs $param ) < 256;
347
$target .= " --ttl-inc $param";
348
} elsif ( $1 =~ /\-/ ) {
349
$target .= " --ttl-dec $param";
351
$target .= " --ttl-set $param";
355
fatal_error "HL is not supported in IPv4 - use TTL instead" if $family == F_IPV4;
356
fatal_error "Invalid HL specification( $cmd/$rest )" if $rest;
357
fatal_error "Chain designator $designator not allowed with HL" if $designator && ! ( $designator eq 'F' );
361
$cmd =~ /^HL\(([-+]?\d+)\)$/;
365
fatal_error "Invalid HL specification( $cmd )" unless $param && ( $param = abs $param ) < 256;
368
$target .= " --hl-inc $param";
369
} elsif ( $1 =~ /\-/ ) {
370
$target .= " --hl-dec $param";
372
$target .= " --hl-set $param";
376
assert( $cmd =~ /^IMQ\((\d+)\)$/ );
377
require_capability 'IMQ_TARGET', 'IMQ', 's';
378
$target .= " --todev $1";
381
assert( $cmd =~ /^DSCP\((\w+)\)$/ );
382
require_capability 'DSCP_TARGET', 'The DSCP action', 's';
383
my $dscp = numeric_value( $1 );
384
$dscp = $dscpmap{$1} unless defined $dscp;
385
fatal_error( "Invalid DSCP ($1)" ) unless defined $dscp && $dscp <= 0x38 && ! ( $dscp & 1 );
386
$target .= ' --set-dscp ' . in_hex( $dscp );
389
assert( $cmd =~ /^TOS\((.+)\)$/ );
390
$target .= decode_tos( $1 , 2 );
244
395
if ( $source eq $fw ) {
336
490
$mark =~ s/^[|&]//;
339
if ( $target eq 'sticky' ) {
340
if ( $chain eq 'tcout' ) {
343
fatal_error "SAME rules are only allowed in the PREROUTING and OUTPUT chains" if $chain ne 'tcpre';
346
$restriction = DESTIFACE_DISALLOW;
348
ensure_mangle_chain($target);
351
} elsif ( $target eq 'IPMARK' ) {
352
my ( $srcdst, $mask1, $mask2, $shift ) = ('src', 255, 0, 0 );
354
require_capability 'IPMARK_TARGET', 'IPMARK', 's';
356
if ( $cmd =~ /^IPMARK\((.+?)\)$/ ) {
360
my ( $sd, $m1, $m2, $s , $bad ) = split ',', $params;
362
fatal_error "Invalid IPMARK parameters ($params)" if $bad;
363
fatal_error "Invalid IPMARK parameter ($sd)" unless ( $sd eq 'src' || $sd eq 'dst' );
366
if ( supplied $m1 ) {
367
$val = numeric_value ($m1);
368
fatal_error "Invalid Mask ($m1)" unless defined $val && $val && $val <= 0xffffffff;
369
$mask1 = in_hex ( $val & 0xffffffff );
372
if ( supplied $m2 ) {
373
$val = numeric_value ($m2);
374
fatal_error "Invalid Mask ($m2)" unless defined $val && $val <= 0xffffffff;
375
$mask2 = in_hex ( $val & 0xffffffff );
379
$val = numeric_value ($s);
380
fatal_error "Invalid Shift Bits ($s)" unless defined $val && $val >= 0 && $val < 128;
384
fatal_error "Invalid MARK/CLASSIFY ($cmd)" unless $cmd eq 'IPMARK';
387
$target = "IPMARK --addr $srcdst --and-mask $mask1 --or-mask $mask2 --shift $shift";
388
} elsif ( $target eq 'TPROXY' ) {
389
require_capability( 'TPROXY_TARGET', 'Use of TPROXY', 's');
391
fatal_error "Invalid TPROXY specification( $cmd/$rest )" if $rest;
395
$cmd =~ /TPROXY\((.+?)\)$/;
399
fatal_error "Invalid TPROXY specification( $cmd )" unless defined $params;
401
( $mark, my $port, my $ip, my $bad ) = split ',', $params;
403
fatal_error "Invalid TPROXY specification( $cmd )" if defined $bad;
406
$port = validate_port( 'tcp', $port );
411
$target .= " --on-port $port";
413
if ( supplied $ip ) {
414
if ( $family == F_IPV6 ) {
415
$ip = $1 if $ip =~ /^\[(.+)\]$/ || $ip =~ /^<(.+)>$/;
418
validate_address $ip, 1;
419
$target .= " --on-ip $ip";
422
$target .= ' --tproxy-mark';
423
} elsif ( $target eq 'TTL' ) {
424
fatal_error "TTL is not supported in IPv6 - use HL instead" if $family == F_IPV6;
425
fatal_error "Invalid TTL specification( $cmd/$rest )" if $rest;
426
fatal_error "Chain designator $designator not allowed with TTL" if $designator && ! ( $designator eq 'F' );
430
$cmd =~ /^TTL\(([-+]?\d+)\)$/;
434
fatal_error "Invalid TTL specification( $cmd )" unless $param && ( $param = abs $param ) < 256;
437
$target .= " --ttl-inc $param";
438
} elsif ( $1 =~ /\-/ ) {
439
$target .= " --ttl-dec $param";
441
$target .= " --ttl-set $param";
443
} elsif ( $target eq 'HL' ) {
444
fatal_error "HL is not supported in IPv4 - use TTL instead" if $family == F_IPV4;
445
fatal_error "Invalid HL specification( $cmd/$rest )" if $rest;
446
fatal_error "Chain designator $designator not allowed with HL" if $designator && ! ( $designator eq 'F' );
450
$cmd =~ /^HL\(([-+]?\d+)\)$/;
454
fatal_error "Invalid HL specification( $cmd )" unless $param && ( $param = abs $param ) < 256;
457
$target .= " --hl-inc $param";
458
} elsif ( $1 =~ /\-/ ) {
459
$target .= " --hl-dec $param";
461
$target .= " --hl-set $param";
463
} elsif ( $target eq 'IMQ' ) {
464
assert( $cmd =~ /^IMQ\((\d+)\)$/ );
465
require_capability 'IMQ_TARGET', 'IMQ', 's';
466
$target .= " --todev $1";
493
if ( my $f = $processtcc{$target} ) {