forked from extern/shorewall_code
Some small tweaks to the marks file processing
Signed-off-by: Tom Eastep <teastep@shorewall.net>
This commit is contained in:
parent
1d84f27efe
commit
584b0ac50e
@ -4768,15 +4768,20 @@ sub verify_small_mark( $ ) {
|
||||
|
||||
sub validate_mark( $ ) {
|
||||
my $mark = shift;
|
||||
my $val;
|
||||
fatal_error "Missing MARK" unless supplied $mark;
|
||||
|
||||
if ( $mark =~ '/' ) {
|
||||
my @marks = split '/', $mark;
|
||||
fatal_error "Invalid MARK ($mark)" unless @marks == 2;
|
||||
verify_mark $_ for @marks;
|
||||
$val = @marks[0];
|
||||
} else {
|
||||
verify_mark $mark;
|
||||
$val = $mark;
|
||||
}
|
||||
|
||||
return numeric_value $val if defined( WANTARRAY );
|
||||
}
|
||||
|
||||
#
|
||||
|
@ -42,45 +42,6 @@ our @EXPORT = qw( process_tc setup_tc );
|
||||
our @EXPORT_OK = qw( process_tc_rule initialize );
|
||||
our $VERSION = 'MODULEVERSION';
|
||||
|
||||
my %tcs = ( T => { chain => 'tcpost',
|
||||
connmark => 0,
|
||||
fw => 1,
|
||||
fwi => 0,
|
||||
} ,
|
||||
CT => { chain => 'tcpost' ,
|
||||
target => 'CONNMARK --set-mark' ,
|
||||
connmark => 1 ,
|
||||
fw => 1 ,
|
||||
fwi => 0,
|
||||
} ,
|
||||
C => { target => 'CONNMARK --set-mark' ,
|
||||
connmark => 1 ,
|
||||
fw => 1 ,
|
||||
fwi => 1 ,
|
||||
} ,
|
||||
P => { chain => 'tcpre' ,
|
||||
connmark => 0 ,
|
||||
fw => 0 ,
|
||||
fwi => 0 ,
|
||||
} ,
|
||||
CP => { chain => 'tcpre' ,
|
||||
target => 'CONNMARK --set-mark' ,
|
||||
connmark => 1 ,
|
||||
fw => 0 ,
|
||||
fwi => 0 ,
|
||||
} ,
|
||||
F => { chain => 'tcfor' ,
|
||||
connmark => 0 ,
|
||||
fw => 0 ,
|
||||
fwi => 0 ,
|
||||
} ,
|
||||
CF => { chain => 'tcfor' ,
|
||||
connmark => 1 ,
|
||||
fw => 0 ,
|
||||
fwi => 0 ,
|
||||
} ,
|
||||
);
|
||||
|
||||
use constant { NOMARK => 0 ,
|
||||
SMALLMARK => 1 ,
|
||||
HIGHMARK => 2
|
||||
@ -207,6 +168,45 @@ sub initialize( $ ) {
|
||||
sub process_tc_rule1( $$$$$$$$$$$$$$$$ ) {
|
||||
my ( $originalmark, $source, $dest, $proto, $ports, $sports, $user, $testval, $length, $tos , $connbytes, $helper, $headers, $probability , $dscp , $state ) = @_;
|
||||
|
||||
my %tcs = ( T => { chain => 'tcpost',
|
||||
connmark => 0,
|
||||
fw => 1,
|
||||
fwi => 0,
|
||||
} ,
|
||||
CT => { chain => 'tcpost' ,
|
||||
target => 'CONNMARK --set-mark' ,
|
||||
connmark => 1 ,
|
||||
fw => 1 ,
|
||||
fwi => 0,
|
||||
} ,
|
||||
C => { target => 'CONNMARK --set-mark' ,
|
||||
connmark => 1 ,
|
||||
fw => 1 ,
|
||||
fwi => 1 ,
|
||||
} ,
|
||||
P => { chain => 'tcpre' ,
|
||||
connmark => 0 ,
|
||||
fw => 0 ,
|
||||
fwi => 0 ,
|
||||
} ,
|
||||
CP => { chain => 'tcpre' ,
|
||||
target => 'CONNMARK --set-mark' ,
|
||||
connmark => 1 ,
|
||||
fw => 0 ,
|
||||
fwi => 0 ,
|
||||
} ,
|
||||
F => { chain => 'tcfor' ,
|
||||
connmark => 0 ,
|
||||
fw => 0 ,
|
||||
fwi => 0 ,
|
||||
} ,
|
||||
CF => { chain => 'tcfor' ,
|
||||
connmark => 1 ,
|
||||
fw => 0 ,
|
||||
fwi => 0 ,
|
||||
} ,
|
||||
);
|
||||
|
||||
our %tccmd;
|
||||
|
||||
unless ( %tccmd ) {
|
||||
@ -852,7 +852,496 @@ sub process_tc_rule( ) {
|
||||
process_tc_rule1( $originalmark, $source, $dest, $proto, $ports, $sports, $user, $testval, $length, $tos , $connbytes, $helper, $headers, $probability , $dscp , $state );
|
||||
}
|
||||
}
|
||||
|
||||
sub process_mark_rule( $$$$$$$$$$$$$$$$ ) {
|
||||
my ( $action, $source, $dest, $proto, $ports, $sports, $user, $testval, $length, $tos , $connbytes, $helper, $headers, $probability , $dscp , $state ) = @_;
|
||||
|
||||
use constant {
|
||||
PREROUTING => 1,
|
||||
INPUT => 2,
|
||||
FORWARD => 4,
|
||||
OUTPUT => 8,
|
||||
POSTROUTING => 16,
|
||||
ALL => 31,
|
||||
STICKY => 32,
|
||||
STICKO => 64,
|
||||
};
|
||||
|
||||
my %designators {
|
||||
P => PREROUTING,
|
||||
I => INPUT,
|
||||
F => FORWARD,
|
||||
O => OUTPUT,
|
||||
T => POSTROUTING };
|
||||
|
||||
my %chainnames = ( PREROUTING => 'tcpre',
|
||||
INPUT => 'tcin',
|
||||
FORWARD => 'tcfor',
|
||||
OUTPUT => 'tcout',
|
||||
POSTROUTING => 'tcpost',
|
||||
sticky => 'sticky',
|
||||
stocko => 'sticko' );
|
||||
|
||||
our $target = '';
|
||||
my $junk = '';
|
||||
my $raw_matches = '';
|
||||
our $chain = '';
|
||||
our $matches = '';
|
||||
our $params = '';
|
||||
our $done = 0;
|
||||
my $default_chain;
|
||||
my $divertref;
|
||||
my $restrictions = 0;
|
||||
|
||||
sub handle_mark_param( $ ) {
|
||||
my ( $option ) = @_;
|
||||
my $and_or = '';
|
||||
my $and_or = $1 if $params =~ s/^([|&])//;
|
||||
|
||||
if ( $params =~ /-/ ) {
|
||||
#
|
||||
# A Mark Range
|
||||
#
|
||||
fatal_error "'|' and '&' may not be used with a mark range" if $and_or;
|
||||
fatal_error "A mark range is is not allowed with ACTION $command" if $command !~ /^(?:CONN)?MARK$/;
|
||||
my ( $mark, $mark2 ) = split /-/, $mark, 2;
|
||||
my $markval = validate_mark $mark;
|
||||
fatal_error "Invalid mark range ($mark-$mark2)" if $mark =~ m'/';
|
||||
my $mark2val = validate_mark $mark2;
|
||||
fatal_error "Invalid mark range ($mark-$mark2)" unless $markval < $mark2val;
|
||||
require_capability 'STATISTIC_MATCH', 'A mark range', 's';
|
||||
( $mark2, my $mask ) = split '/', $mark2;
|
||||
$mask = $globals{TC_MASK} unless supplied $mask;
|
||||
|
||||
my $increment = 1;
|
||||
my $shift = 0;
|
||||
|
||||
$increment <<= 1, $shift++ until $increment & $mask;
|
||||
|
||||
$mask = in_hex $mask;
|
||||
|
||||
my $marks = ( ( $mark2val - $markval ) >> $shift ) + 1;
|
||||
|
||||
my $chainref = ensure_chain( 'mangle', $chain = $chainnames{$chain} );
|
||||
|
||||
for ( my $packet = 0; $packet < $marks; $packet++, $markval += $increment ) {
|
||||
my $match = "-m statistic --mode nth --every $marks --packet $packet ";
|
||||
|
||||
expand_rule( $chainref,
|
||||
$restrictions{$chain} | $restriction,
|
||||
'' ,
|
||||
$match .
|
||||
do_user( $user ) .
|
||||
do_test( $testval, $globals{TC_MASK} ) .
|
||||
do_test( $testval, $globals{TC_MASK} ) .
|
||||
do_length( $length ) .
|
||||
do_tos( $tos ) .
|
||||
do_connbytes( $connbytes ) .
|
||||
do_helper( $helper ) .
|
||||
do_headers( $headers ) .
|
||||
do_probability( $probability ) .
|
||||
do_dscp( $dscp ) .
|
||||
state_match( $state ) .
|
||||
$raw_matches ,
|
||||
$source ,
|
||||
$dest ,
|
||||
'' ,
|
||||
"$target " . join( '/', in_hex( $markval ) , $mask ) ,
|
||||
'',
|
||||
$target ,
|
||||
$exceptionrule );
|
||||
}
|
||||
|
||||
$done = 1;
|
||||
} else {
|
||||
my $val = validate_mark( $mark = $params );
|
||||
#
|
||||
# A Single Mark
|
||||
#
|
||||
if ( $config{PROVIDER_OFFSET} ) {
|
||||
my $limit = $globals{TC_MASK};
|
||||
unless ( have_capability 'FWMARK_RT_MASK' ) {
|
||||
fatal_error "Marks <= $limit may not be set in the PREROUTING or OUTPUT chains when HIGH_ROUTE_MARKS=Yes"
|
||||
if $val && ( $chain && ( PREROUTING | OUTPUT ) ) && $val <= $globals{TC_MASK};
|
||||
}
|
||||
}
|
||||
|
||||
if ( $option ) {
|
||||
$target = join( ' ', $target, $option );
|
||||
} else {
|
||||
$target = join( ' ', $target, $and_or eq '|' ? '--or-mark' : $and_or ? '--and-mark' : '--set-mark' );
|
||||
}
|
||||
|
||||
( $mark, my $mask ) = split '/', $mark;
|
||||
|
||||
$mask = $globals{TC_MASK} unless supplied $mask;
|
||||
|
||||
$target = join( ' ', $target , join( in_hex( $mark ) , in_hex( $mask ) ) );
|
||||
}
|
||||
};
|
||||
|
||||
my ( $command, $designator ) = split_action( $action );
|
||||
|
||||
if ( supplied $designator ) {
|
||||
fatal_error "Invalid chain designator ( $designator )" unless $designators{$designator};
|
||||
}
|
||||
|
||||
( $command , $params ) = get_target_param1( $command );
|
||||
|
||||
my $commandref = $commands{$command};
|
||||
|
||||
fatal_error "Invalid ACTION ($command)" unless $commandref;
|
||||
|
||||
if ( $command eq 'INLINE' ) {
|
||||
( $action, $command, $params, $junk, $raw ) = handle_inline( $action, $command, $params, '' );
|
||||
} elsif ( $config{INLINE_MATCHES} ) {
|
||||
$raw = get_inline_matches( $command eq 'JUMP' );
|
||||
}
|
||||
|
||||
if ( $source =~ /^\$FW/ ) {
|
||||
fatal_error 'Rules with SOURCE $FW must use the OUTPUT chain' if $designator && $designator ne OUTPUT;
|
||||
$default_chain = OUTPUT;
|
||||
} elsif ( $dest =~ /^\$FW/ ) {
|
||||
fatal_error 'Rules with DEST $FW must use the INPUT chain' if $designator && $designator ne INPUT;
|
||||
$default_chain = INPUT;
|
||||
} else {
|
||||
$default_chain = $config{MARK_IN_FORWARD_CHAIN} ? FORWARD | PREROUTING;
|
||||
}
|
||||
|
||||
my %commands = (
|
||||
CHECKSUM => {
|
||||
defaultchain => 0,
|
||||
allowedchains => ALL,
|
||||
minparams => 0,
|
||||
maxparams => 0 ,
|
||||
function => sub() {
|
||||
$target = 'CHECKSUM';
|
||||
},
|
||||
},
|
||||
|
||||
CLASSIFY => {
|
||||
defaultchain => POSTROUTING,
|
||||
allowdchains => PREROUTING,
|
||||
minparams => 1,
|
||||
maxparams => 1,
|
||||
function => sub() {
|
||||
fatal_error "Valid class ID expected ($params)" unless $params =~ /^([0-9a-fA-F]+:[0-9a-fA-F]+)$/;
|
||||
$target = "CLASSIFY --set-class $params";
|
||||
},
|
||||
},
|
||||
|
||||
CONNMARK => {
|
||||
defaultchain => 0,
|
||||
allowedchains => ALL,
|
||||
minparams => 1,
|
||||
maxparams => 1,
|
||||
function => sub () {
|
||||
$chain = $designator || $default_chain;
|
||||
$target = 'CONNTRACK';
|
||||
handle_mark_param('');
|
||||
},
|
||||
},
|
||||
|
||||
CONTINUE => {
|
||||
defaultchain => 0,
|
||||
allowedchains => ALL,
|
||||
minparams => 0,
|
||||
maxparams => 0,
|
||||
function => sub () {
|
||||
$chain = $designator || $default_chain;
|
||||
$target = 'RETURN';
|
||||
},
|
||||
},
|
||||
|
||||
DIVERT => {
|
||||
defaultchain => PREROUTING,
|
||||
allowedchains => PREROUTING,
|
||||
minparams => 0,
|
||||
maxparams => 0,
|
||||
function => sub () {
|
||||
fatal_error 'DIVERT is only allowed in the PREROUTING chain' if $designator && $designator != PREROUTING;
|
||||
$chain = PREROUTING;
|
||||
|
||||
my $mark = in_hex( $globals{TPROXY_MARK} ) . '/' . in_hex( $globals{TPROXY_MARK} );
|
||||
|
||||
unless ( $divertref ) {
|
||||
$divertref = new_chain( 'mangle', 'divert' );
|
||||
add_ijump( $divertref , j => 'MARK', targetopts => "--set-mark $mark" );
|
||||
add_ijump( $divertref , j => 'ACCEPT' );
|
||||
}
|
||||
|
||||
$target = 'divert';
|
||||
|
||||
$matches = '! --tcp-flags FIN,SYN,RST,ACK SYN -m socket --transparent ';
|
||||
},
|
||||
},
|
||||
|
||||
DSCP => {
|
||||
defaultchain => 0,
|
||||
allowedchains => PREROUTING | FORWARD | OUTPUT | POSTROUTING,
|
||||
minparams => 1,
|
||||
maxparams => 1,
|
||||
function => sub () {
|
||||
require_capability 'DSCP_TARGET', 'The DSCP action', 's';
|
||||
my $dscp = numeric_value( $params );
|
||||
$dscp = $dscpmap{$1} unless defined $dscp;
|
||||
fatal_error( "Invalid DSCP ($params)" ) unless defined $dscp && $dscp <= 0x38 && ! ( $dscp & 1 );
|
||||
$target = 'DSCP --set-dscp ' . in_hex( $dscp );
|
||||
},
|
||||
},
|
||||
|
||||
HL => {
|
||||
defaultchain => FORWARD,
|
||||
allowedchains => PREROUTING | FORWARD,
|
||||
minparams => 1,
|
||||
maxparams => 1,
|
||||
function => sub() {
|
||||
fatal_error "HL is not supported in IPv4 - use TTL instead" if $family == F_IPV4;
|
||||
|
||||
$chain = $designator || 'tcfor';
|
||||
|
||||
$params =~ /^([-+]?(\d+))$/;
|
||||
|
||||
fatal_error "Invalid HL specification( $cmd )" unless supplied( $1 ) && ( $1 eq $2 || $2 != 0 ) && ( $params = abs $params ) < 256;
|
||||
|
||||
$target = 'HL';
|
||||
|
||||
if ( $1 =~ /^\+/ ) {
|
||||
$target .= " --hl-inc $params";
|
||||
} elsif ( $1 =~ /\-/ ) {
|
||||
$target .= " --hl-dec $params";
|
||||
} else {
|
||||
$target .= " --hl-set $params";
|
||||
};
|
||||
},
|
||||
},
|
||||
|
||||
IMQ => {
|
||||
defaultchain => PREROUTING,
|
||||
allowedchains => PREROUTING,
|
||||
minparams => 1,
|
||||
maxparams => 1,
|
||||
function => sub () {
|
||||
require_capability 'IMQ_TARGET', 'IMQ', 's';
|
||||
my $imq = numeric_value( $params );
|
||||
fatal_error "Invalid IMQ number ($params)" unless defined $imq;
|
||||
$target = "IMQ --todev $imq";
|
||||
},
|
||||
},
|
||||
|
||||
JUMP => {
|
||||
defaultchain => 0,
|
||||
allowedchains => ALL,
|
||||
minparams => 0,
|
||||
maxparams => 1,
|
||||
function => sub () {
|
||||
my ( $tgt, $options ) = split( ' ', $params );
|
||||
fatal_error "Unknown target ( $tgt )" unless supplied $tgt;
|
||||
$target = $params;
|
||||
},
|
||||
},
|
||||
|
||||
IPMARK => {
|
||||
defaultchain => 0,
|
||||
allowedchains => ALL,
|
||||
minparams => 0,
|
||||
maxparams => 1,
|
||||
function => sub () {
|
||||
my ( $srcdst, $mask1, $mask2, $shift ) = ('src', 255, 0, 0 );
|
||||
|
||||
require_capability 'IPMARK_TARGET', 'IPMARK', 's';
|
||||
$chain = $designator || $default_chain;
|
||||
|
||||
if ( $supplied $params ) {
|
||||
my ( $sd, $m1, $m2, $s , $bad ) = split ',', $params;
|
||||
|
||||
fatal_error "Invalid IPMARK parameters ($params)" if $bad;
|
||||
fatal_error "Invalid IPMARK parameter ($sd)" unless ( $sd eq 'src' || $sd eq 'dst' );
|
||||
$srcdst = $sd;
|
||||
|
||||
if ( supplied $m1 ) {
|
||||
$val = numeric_value ($m1);
|
||||
fatal_error "Invalid Mask ($m1)" unless defined $val && $val && $val <= 0xffffffff;
|
||||
$mask1 = in_hex ( $val & 0xffffffff );
|
||||
}
|
||||
|
||||
if ( supplied $m2 ) {
|
||||
$val = numeric_value ($m2);
|
||||
fatal_error "Invalid Mask ($m2)" unless defined $val && $val <= 0xffffffff;
|
||||
$mask2 = in_hex ( $val & 0xffffffff );
|
||||
}
|
||||
|
||||
if ( defined $s ) {
|
||||
$val = numeric_value ($s);
|
||||
fatal_error "Invalid Shift Bits ($s)" unless defined $val && $val >= 0 && $val < 128;
|
||||
$shift = $s;
|
||||
}
|
||||
};
|
||||
|
||||
$target = "IPMARK --addr $srcdst --and-mask $mask1 --or-mask $mask2 --shift $shift";
|
||||
},
|
||||
},
|
||||
|
||||
MARK => {
|
||||
defaultchain => 0,
|
||||
allowedchains => ALL,
|
||||
minparams => 1,
|
||||
maxparams => 1,
|
||||
function => sub () {
|
||||
$chain = $designator || $default_chain;
|
||||
$target = 'CONNTRACK';
|
||||
handle_mark_param('');
|
||||
},
|
||||
},
|
||||
|
||||
RESTORE => {
|
||||
defaultchain => 0,
|
||||
allowedchains => PREROUTING | FORWARD,
|
||||
minparams => 0,
|
||||
maxparams => 1,
|
||||
function => sub () {
|
||||
$chain = $designator || $default_chain;
|
||||
$target = 'CONNTRACK';
|
||||
handle_mark_param( '--restore-mark' );
|
||||
},
|
||||
},
|
||||
|
||||
SAME => {
|
||||
defaultchain => PREROUTING,
|
||||
allowedchains => PREROUTING | OUTPUT | STICKY | STICKO,
|
||||
minparams => 0,
|
||||
maxparams => 1,
|
||||
function => sub() {
|
||||
$chain = $designator || $default_chain;
|
||||
fatal_error "SAME rules are only allowed in the PREROUTING and OUTPUT chains" unless $chain & ( PREROUTING | OUTPUT );
|
||||
$chain = $chain == PREROUTING ? STICKY : STICKO;
|
||||
$restriction = DESTIFACE_DISALLOW;
|
||||
ensure_mangle_chain($target);
|
||||
$sticky++;
|
||||
},
|
||||
},
|
||||
|
||||
SAVE => {
|
||||
defaultchain => PREROUTING,
|
||||
allowedchains => PREROUTING | FORWARD,
|
||||
minparams => 0,
|
||||
maxparams => 1,
|
||||
function => sub () {
|
||||
$chain = $designator || $default_chain;
|
||||
$target = 'CONNTRACK';
|
||||
handle_mark_param( '--save-mark' );
|
||||
},
|
||||
},
|
||||
|
||||
TOS => {
|
||||
defaultchain => 0,
|
||||
allowedchains => PREROUTING | FORWARD | OUTPUT | POSTROUTING,
|
||||
minparams => 1,
|
||||
maxparams => 1,
|
||||
function => sub() {
|
||||
$target .= decode_tos( $1 , 2 );
|
||||
},
|
||||
},
|
||||
|
||||
TPROXY => {
|
||||
defaultchain => PREROUTING,
|
||||
allowedchains => PREROUTING,
|
||||
minparams => 0,
|
||||
maxparams => 2,
|
||||
function => sub() {
|
||||
require_capability( 'TPROXY_TARGET', 'Use of TPROXY', 's');
|
||||
|
||||
$chain = 'PREROUTING';
|
||||
|
||||
my ( $port, $ip, $bad );
|
||||
|
||||
if ( $params ) {
|
||||
( $port, $ip, $bad ) = split_list $params, 'Parameter';
|
||||
fatal_error "Invalid TPROXY specification( TPROXY($params) )" if defined $bad;
|
||||
}
|
||||
|
||||
$mark = in_hex( $globals{TPROXY_MARK} ) . '/' . in_hex( $globals{TPROXY_MARK} );
|
||||
|
||||
if ( $port ) {
|
||||
$port = validate_port( 'tcp', $port );
|
||||
} else {
|
||||
$port = 0;
|
||||
}
|
||||
|
||||
$target = "TPROXY --on-port $port";
|
||||
|
||||
if ( supplied $ip ) {
|
||||
if ( $family == F_IPV6 ) {
|
||||
if ( $ip =~ /^\[(.+)\]$/ || $ip =~ /^<(.+)>$/ ) {
|
||||
$ip = $1;
|
||||
} elsif ( $ip =~ /^\[(.+)\]\/(\d+)$/ ) {
|
||||
$ip = join( '/', $1, $2 );
|
||||
}
|
||||
}
|
||||
|
||||
validate_address $ip, 1;
|
||||
$target .= " --on-ip $ip";
|
||||
}
|
||||
|
||||
$target .= " --tproxy-mark $mark";
|
||||
|
||||
$exceptionrule = '-p tcp ';
|
||||
|
||||
},
|
||||
},
|
||||
|
||||
TTL => {
|
||||
defaultchain => FORWARD,
|
||||
allowedchains => PREROUTING | FORWARD,
|
||||
minparams => 1,
|
||||
maxparams => 1,
|
||||
function => sub() {
|
||||
fatal_error "TTL is not supported in IPv6 - use HL instead" if $family == F_IPV6;
|
||||
fatal_error "Invalid TTL specification( $cmd/$rest )" if $rest;
|
||||
|
||||
$chain = $designator || FORWARD;
|
||||
$target = 'TTL';
|
||||
|
||||
$params =~ /^([-+]?(\d+))$/;
|
||||
|
||||
fatal_error "Invalid TTL specification( TTL($params) )" unless supplied( $1 ) && ( $1 eq $2 || $2 != 0 ) && ( $param = abs $param ) < 256;
|
||||
|
||||
if ( $1 =~ /^\+/ ) {
|
||||
$target .= " --ttl-inc $params";
|
||||
} elsif ( $1 =~ /\-/ ) {
|
||||
$target .= " --ttl-dec $params";
|
||||
} else {
|
||||
$target .= " --ttl-set $params";
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
);
|
||||
|
||||
my @params = split_list1( $params );
|
||||
|
||||
if ( @params > $commandref->{maxparams} } {
|
||||
if ( $commandref->{maxparams} == 1 ) {
|
||||
fatal_error "The $command ACTION only accepts one parmeter";
|
||||
} else {
|
||||
fatal_error "The $command ACTION only accepts $commandref->{maxparams} parmeters";
|
||||
}
|
||||
}
|
||||
|
||||
if ( @params < $commandref->{minparams} ) {
|
||||
if ( $commandref->{maxparams} == 1 ) {
|
||||
fatal_error "The $command requires a parameter";
|
||||
} else {
|
||||
fatal_error "The $command ACTION only requires at least $commandref->{maxparams} parmeters";
|
||||
}
|
||||
}
|
||||
|
||||
$commandref->function();
|
||||
|
||||
$chain ||= $designator;
|
||||
|
||||
|
||||
}
|
||||
sub rate_to_kbit( $ ) {
|
||||
my $rate = $_[0];
|
||||
|
||||
|
@ -109,10 +109,10 @@
|
||||
|
||||
<para>A chain-designator may not be specified if the SOURCE or DEST
|
||||
columns begin with '$FW'. When the SOURCE is $FW, the generated rule
|
||||
is always placed in the OUTPUT chain.if DEST is '$FW', then the rule
|
||||
is placed in the OUTPUT chain.</para>
|
||||
is always placed in the OUTPUT chain. If DEST is '$FW', then the
|
||||
rule is placed in the OUTPUT chain.</para>
|
||||
|
||||
<para>Where a command takes parameteers, those parameters are
|
||||
<para>Where a command takes parameters, those parameters are
|
||||
enclosed in parentheses ("(....)") and separated by commas.</para>
|
||||
|
||||
<para>The <replaceable>command</replaceable> may be one of the
|
||||
|
Loading…
Reference in New Issue
Block a user