Implement an alternate way of specifying column contents.

Signed-off-by: Tom Eastep <teastep@shorewall.net>
This commit is contained in:
Tom Eastep 2011-09-25 17:08:53 -07:00
parent da5b6b99d4
commit 9a4dfc4394
12 changed files with 364 additions and 48 deletions

View File

@ -141,7 +141,8 @@ sub process_accounting_rule( ) {
$jumpchainref = 0;
my ($action, $chain, $source, $dest, $proto, $ports, $sports, $user, $mark, $ipsec, $headers ) = split_line1 1, 11, 'Accounting File', $accounting_commands;
my ($action, $chain, $source, $dest, $proto, $ports, $sports, $user, $mark, $ipsec, $headers ) =
split_line1 1, 11, 'Accounting File', { action => 0, chain => 1, source => 2, dest => 3, proto => 4, dport => 5, sport => 6, user => 7, mark => 8, ipsec => 9, headers => 10 }, $accounting_commands;
if ( $action eq 'COMMENT' ) {
process_comment;

View File

@ -1338,13 +1338,15 @@ sub supplied( $ ) {
# ensure that it has an appropriate number of columns.
# supply '-' in omitted trailing columns.
#
sub split_line( $$$ ) {
my ( $mincolumns, $maxcolumns, $description ) = @_;
sub split_line( $$$$ ) {
my ( $mincolumns, $maxcolumns, $description, $columnsref ) = @_;
fatal_error "Shorewall Configuration file entries may not contain single quotes, double quotes, single back quotes or backslashes" if $currentline =~ /["'`\\]/;
fatal_error "Non-ASCII gunk in file" if $currentline =~ /[^\s[:print:]]/;
my ( $columns, $pairs ) = split( ';', $currentline );
my @line = split( ' ', $currentline );
fatal_error "Shorewall Configuration file entries may not contain single quotes, double quotes, single back quotes or backslashes" if $columns =~ /["'`\\]/;
fatal_error "Non-ASCII gunk in file" if $columns =~ /[^\s[:print:]]/;
my @line = split( ' ', $columns );
my $line = @line;
@ -1352,31 +1354,44 @@ sub split_line( $$$ ) {
$line-- while $line > 0 && $line[$line-1] eq '-';
fatal_error "Invalid $description entry (too few columns)" if $line < $mincolumns;
push @line, '-' while @line < $maxcolumns;
if ( supplied $pairs ) {
my @pairs = split( ' ', $pairs );
for ( @pairs ) {
fatal_error "Invalid column/value pair ($_)" unless /^(\w+)=(.*)$/;
my ( $column, $value ) = ( lc $1, $2 );
fatal_error "Unknown column ($1)" unless exists $columnsref->{$column};
$column = $columnsref->{$column};
fatal_error "Column $1 already has a value" unless $line[$column] eq '-';
$line[$column] = $value =~ /^"([^"]+)"$/ ? $1 : $value;
}
}
@line;
}
#
# Version of 'split_line' used on files with exceptions
#
sub split_line1( $$$;$ ) {
my ( $mincolumns, $maxcolumns, $description, $nopad) = @_;
sub split_line1( $$$$;$ ) {
my ( $mincolumns, $maxcolumns, $description, $columnsref, $nopad) = @_;
fatal_error "Shorewall Configuration file entries may not contain double quotes, single back quotes or backslashes" if $currentline =~ /["`\\]/;
fatal_error "Non-ASCII gunk in file" if $currentline =~ /[^\s[:print:]]/;
my ( $columns, $pairs ) = split( ';', $currentline );
my @line = split( ' ', $currentline );
fatal_error "Shorewall Configuration file entries may not contain double quotes, single back quotes or backslashes" if $columns =~ /["`\\]/;
fatal_error "Non-ASCII gunk in file" if $columns =~ /[^\s[:print:]]/;
my @line = split( ' ', $columns );
$nopad = { COMMENT => 0 } unless $nopad;
my $first = $line[0];
my $columns = $nopad->{$first};
my $first = $line[0];
my $npcolumns = $nopad->{$first};
if ( defined $columns ) {
fatal_error "Invalid $first entry" if $columns && @line != $columns;
if ( defined $npcolumns ) {
fatal_error "Invalid $first entry" if $npcolumns && @line != $npcolumns;
return @line
}
@ -1392,6 +1407,19 @@ sub split_line1( $$$;$ ) {
push @line, '-' while @line < $maxcolumns;
if ( supplied $pairs ) {
my @pairs = split( ' ', $pairs );
for ( @pairs ) {
fatal_error "Invalid column/value pair ($_)" unless /^(\w+)=(.*)$/;
my ( $column, $value ) = ( lc $1, $2 );
fatal_error "Unknown column ($1)" unless exists $columnsref->{$column};
$column = $columnsref->{$column};
fatal_error "Column $1 already has a value" unless $line[$column] eq '-';
$line[$column] = $value =~ /^"([^"]+)"$/ ? $1 : $value;
}
}
@line;
}

View File

@ -82,7 +82,7 @@ sub process_tos() {
while ( read_a_line ) {
my ($src, $dst, $proto, $sports, $ports , $tos, $mark ) = split_line 6, 7, 'tos file entry';
my ($src, $dst, $proto, $ports, $sports , $tos, $mark ) = split_line 6, 7, 'tos file entry', { source => 0, dest => 1, proto => 2, dport => 3, sport => 4, tos => 5, mark => 6 } ;
$first_entry = 0;
@ -159,7 +159,7 @@ sub setup_ecn()
while ( read_a_line ) {
my ($interface, $hosts ) = split_line 1, 2, 'ecn file entry';
my ($interface, $hosts ) = split_line 1, 2, 'ecn file entry', { interface => 0, hosts => 1 };
fatal_error "Unknown interface ($interface)" unless known_interface $interface;
@ -256,7 +256,7 @@ sub setup_blacklist() {
$first_entry = 0;
}
my ( $networks, $protocol, $ports, $options ) = split_line 1, 4, 'blacklist file';
my ( $networks, $protocol, $ports, $options ) = split_line 1, 4, 'blacklist file', { networks => 0, proto => 1, port => 2, options => 3 };
if ( $options eq '-' ) {
$options = 'src';
@ -358,7 +358,8 @@ sub process_routestopped() {
while ( read_a_line ) {
my ($interface, $hosts, $options , $proto, $ports, $sports ) = split_line 1, 6, 'routestopped file';
my ($interface, $hosts, $options , $proto, $ports, $sports ) =
split_line 1, 6, 'routestopped file', { interface => 1, hosts => 2, options => 3, proto => 4, dport => 5, sport => 6 };
my $interfaceref;
@ -897,7 +898,7 @@ sub setup_mac_lists( $ ) {
while ( read_a_line ) {
my ( $original_disposition, $interface, $mac, $addresses ) = split_line1 3, 4, 'maclist file';
my ( $original_disposition, $interface, $mac, $addresses ) = split_line1 3, 4, 'maclist file', { origdisposition => 0, interface => 1, mac => 2, addresses => 3 };
if ( $original_disposition eq 'COMMENT' ) {
process_comment;

View File

@ -54,7 +54,8 @@ sub initialize() {
#
sub process_one_masq( )
{
my ($interfacelist, $networks, $addresses, $proto, $ports, $ipsec, $mark, $user ) = split_line1 2, 8, 'masq file';
my ($interfacelist, $networks, $addresses, $proto, $ports, $ipsec, $mark, $user ) =
split_line1 2, 8, 'masq file', { interface => 0, source => 1, address => 2, proto => 3, port => 4, ipsec => 5, mark => 6, user => 7 };
if ( $interfacelist eq 'COMMENT' ) {
process_comment;
@ -374,7 +375,7 @@ sub setup_nat() {
while ( read_a_line ) {
my ( $external, $interfacelist, $internal, $allints, $localnat ) = split_line1 3, 5, 'nat file';
my ( $external, $interfacelist, $internal, $allints, $localnat ) = split_line1 3, 5, 'nat file', { external => 1, interface => 1, internal => 2, allints => 3, localnat => 4 };
if ( $external eq 'COMMENT' ) {
process_comment;
@ -407,7 +408,7 @@ sub setup_netmap() {
while ( read_a_line ) {
my ( $type, $net1, $interfacelist, $net2, $net3, $proto, $dport, $sport ) = split_line 4, 8, 'netmap file';
my ( $type, $net1, $interfacelist, $net2, $net3, $proto, $dport, $sport ) = split_line 4, 8, 'netmap file', { type => 0, net1 => 1, interface => 2, net2 => 3, net3 => 4, proto => 4, dport => 5, sport => 6 };
$net3 = ALLIP if $net3 eq '-';

View File

@ -267,7 +267,8 @@ sub start_provider( $$$ ) {
#
sub process_a_provider() {
my ($table, $number, $mark, $duplicate, $interface, $gateway, $options, $copy ) = split_line 6, 8, 'providers file';
my ($table, $number, $mark, $duplicate, $interface, $gateway, $options, $copy ) =
split_line 6, 8, 'providers file', { table => 0, number => 1, mark => 2, duplicate => 3, interface => 4, gateway => 5, options => 6, copy => 7 };
fatal_error "Duplicate provider ($table)" if $providers{$table};
@ -729,7 +730,7 @@ sub add_a_provider( $$ ) {
}
sub add_an_rtrule( ) {
my ( $source, $dest, $provider, $priority ) = split_line 4, 4, 'route_rules file';
my ( $source, $dest, $provider, $priority ) = split_line 4, 4, 'route_rules file', { source => 0, dest => 1, provider => 2, priority => 3 };
our $current_if;
@ -804,7 +805,7 @@ sub add_an_rtrule( ) {
}
sub add_a_route( ) {
my ( $provider, $dest, $gateway, $device ) = split_line 2, 4, 'routes file';
my ( $provider, $dest, $gateway, $device ) = split_line 2, 4, 'routes file', { provider => 0, dest => 1, gateway => 2, device => 3 };
our $current_if;

View File

@ -122,7 +122,8 @@ sub setup_proxy_arp() {
while ( read_a_line ) {
my ( $address, $interface, $external, $haveroute, $persistent ) = split_line 3, 5, $file_opt;
my ( $address, $interface, $external, $haveroute, $persistent ) =
split_line 3, 5, { address => 0, interface => 1, external => 2, haveroute => 3, persistent => 4 }, $file_opt;
if ( $first_entry ) {
progress_message2 "$doing $fn...";

View File

@ -84,7 +84,7 @@ sub setup_notrack() {
while ( read_a_line ) {
my ( $source, $dest, $proto, $ports, $sports, $user ) = split_line1 1, 6, 'Notrack File';
my ( $source, $dest, $proto, $ports, $sports, $user ) = split_line1 1, 6, 'Notrack File', { source => 0, dest => 1, proto => 2, dport => 3, sport => 4, user => 5 };
if ( $source eq 'COMMENT' ) {
process_comment;

View File

@ -77,6 +77,21 @@ my $rule_commands = { COMMENT => 0, FORMAT => 2, SECTION => 2 };
my $action_commands = { COMMENT => 0, FORMAT => 2, SECTION => 2, DEFAULTS => 2 };
my $macro_commands = { COMMENT => 0, FORMAT => 2, SECTION => 2, DEFAULT => 2 };
my %rulecolumns = ( action => 0,
source => 1,
dest => 2,
proto => 3,
dport => 4,
sport => 5,
origdest => 6,
rate => 7,
user => 8,
mark => 9,
connlimit => 10,
time => 11,
headers => 12,
switch => 13 );
use constant { MAX_MACRO_NEST_LEVEL => 5 };
my $macro_nest_level;
@ -297,7 +312,8 @@ sub process_a_policy() {
our %validpolicies;
our @zonelist;
my ( $client, $server, $originalpolicy, $loglevel, $synparams, $connlimit ) = split_line 3, 6, 'policy file';
my ( $client, $server, $originalpolicy, $loglevel, $synparams, $connlimit ) =
split_line 3, 6, 'policy file', { source => 0, dest => 1, policy => 2, loglevel => 3, limit => 4, connlimit => 5 } ;
$loglevel = '' if $loglevel eq '-';
$synparams = '' if $synparams eq '-';
@ -1354,7 +1370,7 @@ sub process_actions() {
open_file $file;
while ( read_a_line ) {
my ( $action ) = split_line 1, 1, 'action file';
my ( $action ) = split_line 1, 1, 'action file' , { action => 0 };
if ( $action =~ /:/ ) {
warning_message 'Default Actions are now specified in /etc/shorewall/shorewall.conf';
@ -1418,11 +1434,11 @@ sub process_action( $) {
my ($target, $source, $dest, $proto, $ports, $sports, $origdest, $rate, $user, $mark, $connlimit, $time, $headers, $condition );
if ( $format == 1 ) {
($target, $source, $dest, $proto, $ports, $sports, $rate, $user, $mark ) = split_line1 1, 9, 'action file', $rule_commands;
($target, $source, $dest, $proto, $ports, $sports, $rate, $user, $mark ) = split_line1 1, 9, 'action file', $rule_commands, {};
$origdest = $connlimit = $time = $headers = $condition = '-';
} else {
($target, $source, $dest, $proto, $ports, $sports, $origdest, $rate, $user, $mark, $connlimit, $time, $headers, $condition )
= split_line1 1, 14, 'action file', $action_commands;
= split_line1 1, 14, 'action file', \%rulecolumns, $action_commands;
}
if ( $target eq 'COMMENT' ) {
@ -1508,10 +1524,10 @@ sub process_macro ( $$$$$$$$$$$$$$$$$$ ) {
my ( $mtarget, $msource, $mdest, $mproto, $mports, $msports, $morigdest, $mrate, $muser, $mmark, $mconnlimit, $mtime, $mheaders, $mcondition );
if ( $format == 1 ) {
( $mtarget, $msource, $mdest, $mproto, $mports, $msports, $mrate, $muser ) = split_line1 1, 8, 'macro file', $rule_commands;
( $mtarget, $msource, $mdest, $mproto, $mports, $msports, $mrate, $muser ) = split_line1 1, 8, 'macro file', \%rulecolumns, $rule_commands;
( $morigdest, $mmark, $mconnlimit, $mtime, $mheaders, $mcondition ) = qw/- - - - - -/;
} else {
( $mtarget, $msource, $mdest, $mproto, $mports, $msports, $morigdest, $mrate, $muser, $mmark, $mconnlimit, $mtime, $mheaders, $mcondition ) = split_line1 1, 14, 'macro file', $rule_commands;
( $mtarget, $msource, $mdest, $mproto, $mports, $msports, $morigdest, $mrate, $muser, $mmark, $mconnlimit, $mtime, $mheaders, $mcondition ) = split_line1 1, 14, 'macro file', \%rulecolumns, $rule_commands;
}
if ( $mtarget eq 'COMMENT' ) {
@ -2322,7 +2338,7 @@ sub build_zone_list( $$$\$\$ ) {
#
sub process_rule ( ) {
my ( $target, $source, $dest, $protos, $ports, $sports, $origdest, $ratelimit, $user, $mark, $connlimit, $time, $headers, $condition )
= split_line1 1, 14, 'rules file', $rule_commands;
= split_line1 1, 14, 'rules file', \%rulecolumns, $rule_commands;
process_comment, return 1 if $target eq 'COMMENT';
process_section( $source ), return 1 if $target eq 'SECTION';

View File

@ -191,7 +191,8 @@ sub initialize( $ ) {
}
sub process_tc_rule( ) {
my ( $originalmark, $source, $dest, $proto, $ports, $sports, $user, $testval, $length, $tos , $connbytes, $helper, $headers ) = split_line1 2, 13, 'tcrules file';
my ( $originalmark, $source, $dest, $proto, $ports, $sports, $user, $testval, $length, $tos , $connbytes, $helper, $headers ) =
split_line1 2, 13, '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 };
our @tccmd;
@ -510,7 +511,7 @@ sub process_flow($) {
}
sub process_simple_device() {
my ( $device , $type , $in_bandwidth , $out_part ) = split_line 1, 4, 'tcinterfaces';
my ( $device , $type , $in_bandwidth , $out_part ) = split_line 1, 4, 'tcinterfaces', { device => 0, type => 1, in_bandwidth => 2, out_bandwidth => 3 };
fatal_error "Duplicate INTERFACE ($device)" if $tcdevices{$device};
fatal_error "Invalid INTERFACE name ($device)" if $device =~ /[:+]/;
@ -644,7 +645,7 @@ sub process_simple_device() {
}
sub validate_tc_device( ) {
my ( $device, $inband, $outband , $options , $redirected ) = split_line 3, 5, 'tcdevices';
my ( $device, $inband, $outband , $options , $redirected ) = split_line 3, 5, 'tcdevices', { device => 0, in_bandwidth => 1, out_bandwidth => 2, options => 3, redirect => 4 };
fatal_error "Invalid tcdevices entry" if $outband eq '-';
@ -807,7 +808,8 @@ sub dev_by_number( $ ) {
}
sub validate_tc_class( ) {
my ( $devclass, $mark, $rate, $ceil, $prio, $options ) = split_line 4, 6, 'tcclasses file';
my ( $devclass, $mark, $rate, $ceil, $prio, $options ) =
split_line 4, 6, 'tcclasses file', { device => 0, mark => 1, rate => 2, ceil => 3, prio => 4, options => 5 };
my $classnumber = 0;
my $devref;
my $device = $devclass;
@ -1028,7 +1030,7 @@ my %validlengths = ( 32 => '0xffe0', 64 => '0xffc0', 128 => '0xff80', 256 => '0x
#
sub process_tc_filter() {
my ( $devclass, $source, $dest , $proto, $portlist , $sportlist, $tos, $length ) = split_line 2, 8, 'tcfilters file';
my ( $devclass, $source, $dest , $proto, $portlist , $sportlist, $tos, $length ) = split_line 2, 8, 'tcfilters file', { device => 0, source => 1, dest => 2, proto => 3, dport => 4, sport => 5, tos => 6, length => 7 };
my ($device, $class, $rest ) = split /:/, $devclass, 3;
@ -1328,7 +1330,7 @@ sub process_tcfilters() {
# Process a tcpri record
#
sub process_tc_priority() {
my ( $band, $proto, $ports , $address, $interface, $helper ) = split_line1 1, 6, 'tcpri';
my ( $band, $proto, $ports , $address, $interface, $helper ) = split_line1 1, 6, 'tcpri', { band => 0, proto => 1, port => 2, address => 3, interface => 4, helper => 5 };
if ( $band eq 'COMMENT' ) {
process_comment;
@ -1666,7 +1668,8 @@ sub setup_traffic_shaping() {
# Process a record in the secmarks file
#
sub process_secmark_rule() {
my ( $secmark, $chainin, $source, $dest, $proto, $dport, $sport, $user, $mark ) = split_line1( 2, 9 , 'Secmarks file' );
my ( $secmark, $chainin, $source, $dest, $proto, $dport, $sport, $user, $mark ) =
split_line1( 2, 9 , 'Secmarks file' , { secmark => 0, chain => 1, source => 2, dest => 3, proto => 4, dport => 5, sport => 6, user => 7, mark => 8 } );
if ( $secmark eq 'COMMENT' ) {
process_comment;

View File

@ -284,7 +284,7 @@ sub setup_tunnels() {
while ( read_a_line ) {
my ( $kind, $zone, $gateway, $gatewayzones ) = split_line1 2, 4, 'tunnels file';
my ( $kind, $zone, $gateway, $gatewayzones ) = split_line1 2, 4, 'tunnels file', { kind => 0, zone => 1, gateway => 2, gateway_zone => 3 };
if ( $kind eq 'COMMENT' ) {
process_comment;

View File

@ -402,7 +402,8 @@ sub process_zone( \$ ) {
my @parents;
my ($zone, $type, $options, $in_options, $out_options ) = split_line 1, 5, 'zones file';
my ($zone, $type, $options, $in_options, $out_options ) =
split_line 1, 5, 'zones file', { zone => 0, type => 1, options => 2, in_options => 3, out_options => 4 };
if ( $zone =~ /(\w+):([\w,]+)/ ) {
$zone = $1;
@ -871,7 +872,7 @@ sub process_interface( $$ ) {
my ( $nextinum, $export ) = @_;
my $netsref = '';
my $filterref = [];
my ($zone, $originalinterface, $bcasts, $options ) = split_line 2, 4, 'interfaces file';
my ($zone, $originalinterface, $bcasts, $options ) = split_line 2, 4, 'interfaces file', { zone => 0, interface => 1, broadcast => 2, options => 3 };
my $zoneref;
my $bridge = '';
@ -1727,7 +1728,7 @@ sub compile_updown() {
#
sub process_host( ) {
my $ipsec = 0;
my ($zone, $hosts, $options ) = split_line 2, 3, 'hosts file';
my ($zone, $hosts, $options ) = split_line 2, 3, 'hosts file', { zone => 0, hosts => 1, options => 2 };
my $zoneref = $zones{$zone};
my $type = $zoneref->{type};

View File

@ -492,6 +492,269 @@ ACCEPT net:\
</example>
</section>
<section id="Pairs">
<title>Alternate Specification of Column Values - Shorewall 4.4.24 and
Later</title>
<para>Some of the configuration files now have a large number of columns.
That makes it awkward to specify a value for one of the right-most columns
as you must have the correct number of intervening '-' columns.</para>
<para>This problem is addressed by allowing column values to be specified
as <replaceable>column-name</replaceable>/<replaceable>value</replaceable>
pairs.</para>
<para>Each file has both required and optional columns. The columns up to
the last required column must be specified in the normal way. After that,
at any point, you can enter a semicolon (':') followed by one or more
specifications of the form:</para>
<simplelist>
<member><replaceable>column-name</replaceable>=<replaceable>value</replaceable></member>
</simplelist>
<para>The value may optionally be enclosed in double quotes.</para>
<para>The following table shows the right-most required column and the
remaining column names for each of the table-oriented configuration
files.</para>
<note>
<para>Column names are case-insensitive.</para>
</note>
<informaltable>
<tgroup cols="3">
<tbody>
<row>
<entry><emphasis role="bold">File</emphasis></entry>
<entry><emphasis role="bold">Right-most required
Column</emphasis></entry>
<entry><emphasis role="bold">Remaining column
names</emphasis></entry>
</row>
<row>
<entry>accounting</entry>
<entry>ACTION</entry>
<entry>chain, source, dest, proto, dport, sport, user, mark,
ipsec, headers</entry>
</row>
<row>
<entry>blacklist</entry>
<entry>ADDRESS/SUBNET</entry>
<entry>proto,port,options</entry>
</row>
<row>
<entry>ecn</entry>
<entry>INTERFACE</entry>
<entry>hosts</entry>
</row>
<row>
<entry>hosts</entry>
<entry>ZONE</entry>
<entry>hosts,options</entry>
</row>
<row>
<entry>interfaces</entry>
<entry>INTERFACE</entry>
<entry>broadcast,options</entry>
</row>
<row>
<entry>maclist</entry>
<entry>MAC</entry>
<entry>addresses</entry>
</row>
<row>
<entry>masq</entry>
<entry>SOURCE</entry>
<entry>address,proto,port,ipsec,mark,user</entry>
</row>
<row>
<entry>nat</entry>
<entry>EXTERNAL</entry>
<entry>interface,internal,allints,localnat</entry>
</row>
<row>
<entry>netmap</entry>
<entry>NET2</entry>
<entry>net3,proto,dport,sport</entry>
</row>
<row>
<entry>notrack</entry>
<entry>SOURCE</entry>
<entry>dest,proto,dport,sport,user</entry>
</row>
<row>
<entry>policy</entry>
<entry>POLICY</entry>
<entry>loglevel,limit,connlimit</entry>
</row>
<row>
<entry>providers</entry>
<entry>GATEWAY</entry>
<entry>options,copy</entry>
</row>
<row>
<entry>proxyarp</entry>
<entry>EXTERNAL</entry>
<entry>haveroute,persistent</entry>
</row>
<row>
<entry>route_rules</entry>
<entry>PRIORITY</entry>
<entry>N/A</entry>
</row>
<row>
<entry>routestopped</entry>
<entry>INTERFACE</entry>
<entry>hosts,options,proto,dport,sport</entry>
</row>
<row>
<entry>rules</entry>
<entry>ACTION</entry>
<entry>source,dest,proto,dport,sport,origdest,rate,user,mark,connlimit,time,headers,switch</entry>
</row>
<row>
<entry>secmarks</entry>
<entry>CHAIN</entry>
<entry>source,dest,proto,dport,sport,user,mark</entry>
</row>
<row>
<entry>tcclasses</entry>
<entry>CEIL</entry>
<entry>prio,options</entry>
</row>
<row>
<entry>tcdevices</entry>
<entry>OUT_BANDWIDTH</entry>
<entry>options,redirect</entry>
</row>
<row>
<entry>tcfilters</entry>
<entry>SOURCE</entry>
<entry>dest,proto,dport,sport,tos,length</entry>
</row>
<row>
<entry>tcinterfaces</entry>
<entry>DEVICE</entry>
<entry>type,in_bandwidth,out_bandwidth</entry>
</row>
<row>
<entry>tcpri</entry>
<entry>BAND</entry>
<entry>proto,port,address,interface,helper</entry>
</row>
<row>
<entry>tcrules</entry>
<entry>SOURCE</entry>
<entry>dest,proto,dport,sport,user,test,length,tos,connbytes,helper,headers</entry>
</row>
<row>
<entry>tos</entry>
<entry>TOS</entry>
<entry>mark</entry>
</row>
<row>
<entry>tunnels</entry>
<entry>ZONE</entry>
<entry>gateway,gateway_zone</entry>
</row>
<row>
<entry>zones</entry>
<entry>ZONE</entry>
<entry>type,options,in_options,out_options</entry>
</row>
</tbody>
</tgroup>
</informaltable>
<para>Example (rules file):</para>
<programlisting>#ACTION SOURCE DEST PROTO DEST
# PORT(S)
DNAT net loc:10.0.0.1 tcp 80 ; mark="88"</programlisting>
</section>
<section>
<title>Addresses</title>