~ubuntu-branches/ubuntu/saucy/shorewall/saucy-proposed

« back to all changes in this revision

Viewing changes to Perl/Shorewall/Tc.pm

  • Committer: Package Import Robot
  • Author(s): Roberto C. Sanchez
  • Date: 2012-04-14 21:57:42 UTC
  • mfrom: (1.3.46)
  • Revision ID: package-import@ubuntu.com-20120414215742-0ejkotwovqesavu7
Tags: 4.5.2.2-1
* New Upstream Version
* Convert to debhelper compatibility level 8

Show diffs side-by-side

added added

removed removed

Lines of Context:
40
40
our @ISA = qw(Exporter);
41
41
our @EXPORT = qw( process_tc setup_tc );
42
42
our @EXPORT_OK = qw( process_tc_rule initialize );
43
 
our $VERSION = '4.5_0';
 
43
our $VERSION = '4.5_2';
44
44
 
45
45
my  %tcs = ( T => { chain  => 'tcpost',
46
46
                    connmark => 0,
194
194
}
195
195
 
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 };
201
201
        $headers = '-';
202
202
    } else {
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 };
205
205
    }
206
206
 
207
207
    our @tccmd;
239
239
    my $device   = '';
240
240
    my $fw       = firewall_zone;
241
241
    my $list;
 
242
    my $restriction = 0;
 
243
    my $cmd;
 
244
    my $rest;
 
245
 
 
246
    my %processtcc = ( sticky => sub() {
 
247
                                          if ( $chain eq 'tcout' ) {
 
248
                                              $target = 'sticko';
 
249
                                          } else {
 
250
                                              fatal_error "SAME rules are only allowed in the PREROUTING and OUTPUT chains" if $chain ne 'tcpre';
 
251
                                          }
 
252
 
 
253
                                          $restriction = DESTIFACE_DISALLOW;
 
254
 
 
255
                                          ensure_mangle_chain($target);
 
256
 
 
257
                                          $sticky++;
 
258
                                      },
 
259
                       IPMARK => sub() {
 
260
                                          my ( $srcdst, $mask1, $mask2, $shift ) = ('src', 255, 0, 0 );
 
261
 
 
262
                                          require_capability 'IPMARK_TARGET', 'IPMARK', 's';
 
263
 
 
264
                                          if ( $cmd =~ /^IPMARK\((.+?)\)$/ ) {
 
265
                                              my $params = $1;
 
266
                                              my $val;
 
267
 
 
268
                                              my ( $sd, $m1, $m2, $s , $bad ) = split ',', $params;
 
269
 
 
270
                                              fatal_error "Invalid IPMARK parameters ($params)" if $bad;
 
271
                                              fatal_error "Invalid IPMARK parameter ($sd)" unless ( $sd eq 'src' || $sd eq 'dst' );
 
272
                                              $srcdst = $sd;
 
273
 
 
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 );
 
278
                                              }
 
279
 
 
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 );
 
284
                                              }
 
285
 
 
286
                                              if ( defined $s ) {
 
287
                                                  $val = numeric_value ($s);
 
288
                                                  fatal_error "Invalid Shift Bits ($s)" unless defined $val && $val >= 0 && $val < 128;
 
289
                                                  $shift = $s;
 
290
                                              }                     
 
291
                                          } else {
 
292
                                              fatal_error "Invalid MARK/CLASSIFY ($cmd)" unless $cmd eq 'IPMARK';
 
293
                                          }
 
294
 
 
295
                                          $target = "IPMARK --addr $srcdst --and-mask $mask1 --or-mask $mask2 --shift $shift";
 
296
                                      },
 
297
                       TPROXY => sub() {
 
298
                                          require_capability( 'TPROXY_TARGET', 'Use of TPROXY', 's');
 
299
 
 
300
                                          fatal_error "Invalid TPROXY specification( $cmd/$rest )" if $rest;
 
301
 
 
302
                                          $chain = 'tcpre';
 
303
 
 
304
                                          $cmd =~ /TPROXY\((.+?)\)$/;
 
305
 
 
306
                                          my $params = $1;
 
307
 
 
308
                                          fatal_error "Invalid TPROXY specification( $cmd )" unless defined $params;
 
309
 
 
310
                                          ( $mark, my $port, my $ip, my $bad ) = split ',', $params;
 
311
 
 
312
                                          fatal_error "Invalid TPROXY specification( $cmd )" if defined $bad;
 
313
 
 
314
                                          if ( $port ) {
 
315
                                              $port = validate_port( 'tcp', $port );
 
316
                                          } else {
 
317
                                              $port = 0;
 
318
                                          }
 
319
 
 
320
                                          $target .= " --on-port $port";
 
321
 
 
322
                                          if ( supplied $ip ) {
 
323
                                              if ( $family == F_IPV6 ) {
 
324
                                                  $ip = $1 if $ip =~ /^\[(.+)\]$/ || $ip =~ /^<(.+)>$/;
 
325
                                              }
 
326
 
 
327
                                              validate_address $ip, 1;
 
328
                                              $target .= " --on-ip $ip";
 
329
                                          }
 
330
 
 
331
                                          $target .= ' --tproxy-mark';
 
332
                                      },
 
333
                       TTL => sub() {
 
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' );
 
337
 
 
338
                                          $chain = 'tcfor';
 
339
 
 
340
                                          $cmd =~ /^TTL\(([-+]?\d+)\)$/;
 
341
 
 
342
                                          my $param =  $1;
 
343
 
 
344
                                          fatal_error "Invalid TTL specification( $cmd )" unless $param && ( $param = abs $param ) < 256;
 
345
 
 
346
                                          if ( $1 =~ /^\+/ ) {
 
347
                                              $target .= " --ttl-inc $param";
 
348
                                          } elsif ( $1 =~ /\-/ ) {
 
349
                                              $target .= " --ttl-dec $param";
 
350
                                          } else {
 
351
                                              $target .= " --ttl-set $param";
 
352
                                          }
 
353
                                      },
 
354
                       HL => sub() {
 
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' );
 
358
 
 
359
                                          $chain = 'tcfor';
 
360
 
 
361
                                          $cmd =~ /^HL\(([-+]?\d+)\)$/;
 
362
 
 
363
                                          my $param =  $1;
 
364
 
 
365
                                          fatal_error "Invalid HL specification( $cmd )" unless $param && ( $param = abs $param ) < 256;
 
366
 
 
367
                                          if ( $1 =~ /^\+/ ) {
 
368
                                              $target .= " --hl-inc $param";
 
369
                                          } elsif ( $1 =~ /\-/ ) {
 
370
                                              $target .= " --hl-dec $param";
 
371
                                          } else {
 
372
                                              $target .= " --hl-set $param";
 
373
                                          }
 
374
                                      },
 
375
                       IMQ => sub() {
 
376
                                          assert( $cmd =~ /^IMQ\((\d+)\)$/ );
 
377
                                          require_capability 'IMQ_TARGET', 'IMQ', 's';
 
378
                                          $target .= " --todev $1";
 
379
                                      },
 
380
                       DSCP => sub() {
 
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 );
 
387
                                      },
 
388
                       TOS => sub() {
 
389
                                          assert( $cmd =~ /^TOS\((.+)\)$/ );
 
390
                                          $target .= decode_tos( $1 , 2 );
 
391
                                      },
 
392
                     );
242
393
 
243
394
    if ( $source ) {
244
395
        if ( $source eq $fw ) {
312
463
        }
313
464
    }
314
465
 
315
 
    my ($cmd, $rest) = split( '/', $mark, 2 );
 
466
    if ( $mark =~ /^TOS/ ) {
 
467
        $cmd = $mark;
 
468
        $rest = '';
 
469
    } else {
 
470
        ($cmd, $rest) = split( '/', $mark, 2 );
 
471
    }
316
472
 
317
473
    $list = '';
318
474
 
319
 
    my $restriction = 0;
320
 
 
321
475
    unless ( $classid ) {
322
476
      MARK:
323
477
        {
336
490
                        $mark =~ s/^[|&]//;
337
491
                    }
338
492
 
339
 
                    if ( $target eq 'sticky' ) {
340
 
                        if ( $chain eq 'tcout' ) {
341
 
                            $target = 'sticko';
342
 
                        } else {
343
 
                            fatal_error "SAME rules are only allowed in the PREROUTING and OUTPUT chains" if $chain ne 'tcpre';
344
 
                        }
345
 
 
346
 
                        $restriction = DESTIFACE_DISALLOW;
347
 
 
348
 
                        ensure_mangle_chain($target);
349
 
 
350
 
                        $sticky++;
351
 
                    } elsif ( $target eq 'IPMARK' ) {
352
 
                        my ( $srcdst, $mask1, $mask2, $shift ) = ('src', 255, 0, 0 );
353
 
 
354
 
                        require_capability 'IPMARK_TARGET', 'IPMARK', 's';
355
 
 
356
 
                        if ( $cmd =~ /^IPMARK\((.+?)\)$/ ) {
357
 
                            my $params = $1;
358
 
                            my $val;
359
 
 
360
 
                            my ( $sd, $m1, $m2, $s , $bad ) = split ',', $params;
361
 
 
362
 
                            fatal_error "Invalid IPMARK parameters ($params)" if $bad;
363
 
                            fatal_error "Invalid IPMARK parameter ($sd)" unless ( $sd eq 'src' || $sd eq 'dst' );
364
 
                            $srcdst = $sd;
365
 
 
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 );
370
 
                            }
371
 
 
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 );
376
 
                            }
377
 
 
378
 
                            if ( defined $s ) {
379
 
                                $val = numeric_value ($s);
380
 
                                fatal_error "Invalid Shift Bits ($s)" unless defined $val && $val >= 0 && $val < 128;
381
 
                                $shift = $s;
382
 
                            }                       
383
 
                        } else {
384
 
                            fatal_error "Invalid MARK/CLASSIFY ($cmd)" unless $cmd eq 'IPMARK';
385
 
                        }
386
 
 
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');
390
 
 
391
 
                        fatal_error "Invalid TPROXY specification( $cmd/$rest )" if $rest;
392
 
 
393
 
                        $chain = 'tcpre';
394
 
 
395
 
                        $cmd =~ /TPROXY\((.+?)\)$/;
396
 
 
397
 
                        my $params = $1;
398
 
 
399
 
                        fatal_error "Invalid TPROXY specification( $cmd )" unless defined $params;
400
 
 
401
 
                        ( $mark, my $port, my $ip, my $bad ) = split ',', $params;
402
 
 
403
 
                        fatal_error "Invalid TPROXY specification( $cmd )" if defined $bad;
404
 
 
405
 
                        if ( $port ) {
406
 
                            $port = validate_port( 'tcp', $port );
407
 
                        } else {
408
 
                            $port = 0;
409
 
                        }
410
 
 
411
 
                        $target .= " --on-port $port";
412
 
 
413
 
                        if ( supplied $ip ) {
414
 
                            if ( $family == F_IPV6 ) {
415
 
                                $ip = $1 if $ip =~ /^\[(.+)\]$/ || $ip =~ /^<(.+)>$/;
416
 
                            }
417
 
 
418
 
                            validate_address $ip, 1;
419
 
                            $target .= " --on-ip $ip";
420
 
                        }
421
 
 
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' );
427
 
 
428
 
                        $chain = 'tcfor';
429
 
 
430
 
                        $cmd =~ /^TTL\(([-+]?\d+)\)$/;
431
 
 
432
 
                        my $param =  $1;
433
 
 
434
 
                        fatal_error "Invalid TTL specification( $cmd )" unless $param && ( $param = abs $param ) < 256;
435
 
 
436
 
                        if ( $1 =~ /^\+/ ) {
437
 
                            $target .= " --ttl-inc $param";
438
 
                        } elsif ( $1 =~ /\-/ ) {
439
 
                            $target .= " --ttl-dec $param";
440
 
                        } else {
441
 
                            $target .= " --ttl-set $param";
442
 
                        }
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' );
447
 
 
448
 
                        $chain = 'tcfor';
449
 
 
450
 
                        $cmd =~ /^HL\(([-+]?\d+)\)$/;
451
 
 
452
 
                        my $param =  $1;
453
 
 
454
 
                        fatal_error "Invalid HL specification( $cmd )" unless $param && ( $param = abs $param ) < 256;
455
 
 
456
 
                        if ( $1 =~ /^\+/ ) {
457
 
                            $target .= " --hl-inc $param";
458
 
                        } elsif ( $1 =~ /\-/ ) {
459
 
                            $target .= " --hl-dec $param";
460
 
                        } else {
461
 
                            $target .= " --hl-set $param";
462
 
                        }
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} ) {
 
494
                        $f->();
467
495
                    }
468
496
 
469
497
                    if ( $rest ) {
510
538
                                     do_connbytes( $connbytes ) .
511
539
                                     do_helper( $helper ) .
512
540
                                     do_headers( $headers ) .
513
 
                                     do_probability( $probability ) ,
 
541
                                     do_probability( $probability ) .
 
542
                                     do_dscp( $dscp ),
514
543
                                     $source ,
515
544
                                     $dest ,
516
545
                                     '' ,
855
884
                            pfifo         => $pfifo,
856
885
                            tablenumber   => 1 ,
857
886
                            redirected    => \@redirected,
858
 
                            default       => 0,
 
887
                            default       => undef,
859
888
                            nextclass     => 2,
860
889
                            qdisc         => $qdisc,
861
890
                            guarantee     => 0,
998
1027
        }
999
1028
    } else {
1000
1029
        fatal_error "Duplicate Class NUMBER ($classnumber)" if $tcref->{$classnumber};
 
1030
        $markval = '-';
1001
1031
    }
1002
1032
 
1003
1033
    if ( $parentclass != 1 ) {
1009
1039
        fatal_error "Unknown Parent class ($parentnum)" unless $parentref && $parentref->{occurs} == 1;
1010
1040
        fatal_error "The class ($parentnum) specifies UMAX and/or DMAX; it cannot serve as a parent" if $parentref->{dmax};
1011
1041
        fatal_error "The class ($parentnum) specifies flow; it cannot serve as a parent"             if $parentref->{flow};
1012
 
        fatal_error "The default class ($parentnum) may not have sub-classes"                        if $devref->{default} == $parentclass;
 
1042
        fatal_error "The default class ($parentnum) may not have sub-classes"                        if ( $devref->{default} || 0 ) == $parentclass;
1013
1043
        $parentref->{leaf} = 0;
1014
1044
        $ratemax  = $parentref->{rate};
1015
1045
        $ratename = q(the parent class's RATE);
1114
1144
    }
1115
1145
 
1116
1146
    unless ( $devref->{classify} || $occurs > 1 ) {
1117
 
        fatal_error "Missing MARK" if $mark eq '-';
1118
 
        warning_message "Class NUMBER ignored -- INTERFACE $device does not have the 'classify' option" if $devclass =~ /:/;
 
1147
        if ( $mark ne '-' ) {
 
1148
            fatal_error "Missing MARK" if $mark eq '-';
 
1149
            warning_message "Class NUMBER ignored -- INTERFACE $device does not have the 'classify' option"     if $devclass =~ /:/;
 
1150
        }
1119
1151
    }
1120
1152
 
1121
1153
    $tcref->{flow}  = $devref->{flow}  unless $tcref->{flow};
1596
1628
        my $devnum  = in_hexp $devref->{number};
1597
1629
        my $r2q     = int calculate_r2q $devref->{out_bandwidth};
1598
1630
 
1599
 
        fatal_error "No default class defined for device $devname" unless $devref->{default};
 
1631
        fatal_error "No default class defined for device $devname" unless defined $devref->{default};
1600
1632
 
1601
1633
        my $device = physical_name $devname;
1602
1634
 
1708
1740
                #
1709
1741
                # add filters
1710
1742
                #
1711
 
                unless ( $devref->{classify} ) {
 
1743
                unless ( $mark eq '-' ) {
1712
1744
                    emit "run_tc filter add dev $device protocol all parent $devicenumber:0 prio " . ( $priority | 20 ) . " handle $mark fw classid $classid" if $tcref->{occurs} == 1;
1713
1745
                }
1714
1746
 
1988
2020
                          mask      => '',
1989
2021
                          connmark  => 0
1990
2022
                        },
 
2023
                        { match     => sub( $ ) { $_[0] =~ /^DSCP\(\w+\)$/ },
 
2024
                          target    => 'DSCP',
 
2025
                          mark      => NOMARK,
 
2026
                          mask      => '',
 
2027
                          connmark  => 0
 
2028
                        },
 
2029
                        { match     => sub( $ ) { $_[0] =~ /^TOS\(.+\)$/ },
 
2030
                          target    => 'TOS',
 
2031
                          mark      => NOMARK,
 
2032
                          mask      => '',
 
2033
                          connmark  => 0
 
2034
                        },
1991
2035
                      );
1992
2036
 
1993
2037
        if ( my $fn = open_file 'tcrules' ) {