diff --git a/Shorewall/Perl/Shorewall/Chains.pm b/Shorewall/Perl/Shorewall/Chains.pm
index 402842341..02418913b 100644
--- a/Shorewall/Perl/Shorewall/Chains.pm
+++ b/Shorewall/Perl/Shorewall/Chains.pm
@@ -169,6 +169,7 @@ our %EXPORT_TAGS = (
do_connbytes
do_helper
do_headers
+ do_condition
have_ipset_rules
record_runtime_address
conditional_rule
@@ -3736,6 +3737,20 @@ sub do_headers( $ ) {
"-m ipv6header ${invert}--header ${headers} ${soft}";
}
+#
+# Generate a -m condition match
+#
+sub do_condition( $ ) {
+ my $condition = shift;
+
+ return '' if $condition eq '-';
+
+ require_capability 'CONDITION_MATCH', 'A non-empty CONDITION column', 's';
+ fatal_error "Invalid condition name ($condition)" unless $condition =~ /^[a-zA-Z]\w*$/;
+
+ "-m condition --condition $condition "
+}
+
#
# Match Source Interface
#
diff --git a/Shorewall/Perl/Shorewall/Config.pm b/Shorewall/Perl/Shorewall/Config.pm
index 26c7f3c93..32527514a 100644
--- a/Shorewall/Perl/Shorewall/Config.pm
+++ b/Shorewall/Perl/Shorewall/Config.pm
@@ -280,6 +280,7 @@ my %capdesc = ( NAT_ENABLED => 'NAT',
ACCOUNT_TARGET => 'ACCOUNT Target',
AUDIT_TARGET => 'AUDIT Target',
RAWPOST_TABLE => 'Rawpost Table',
+ CONDITION_MATCH => 'Condition Match',
CAPVERSION => 'Capability Version',
KERNELVERSION => 'Kernel Version',
);
@@ -444,7 +445,7 @@ sub initialize( $ ) {
STATEMATCH => '-m state --state',
UNTRACKED => 0,
VERSION => "4.4.22.1",
- CAPVERSION => 40423 ,
+ CAPVERSION => 40424 ,
);
#
# From shorewall.conf file
@@ -664,6 +665,7 @@ sub initialize( $ ) {
HEADER_MATCH => undef,
ACCOUNT_TARGET => undef,
AUDIT_TARGET => undef,
+ CONDITION_MATCH => undef,
CAPVERSION => undef,
KERNELVERSION => undef,
);
@@ -2671,6 +2673,10 @@ sub Account_Target() {
}
}
+sub Condition_Match() {
+ qt1( "$iptables -m condition --condition foo" );
+}
+
sub Audit_Target() {
qt1( "$iptables -A $sillyname -j AUDIT --type drop" );
}
@@ -2680,6 +2686,7 @@ our %detect_capability =
AUDIT_TARGET => \&Audit_Target,
ADDRTYPE => \&Addrtype,
CLASSIFY_TARGET => \&Classify_Target,
+ CONDITION_MATCH => \&Condition_Match,
COMMENTS => \&Comments,
CONNLIMIT_MATCH => \&Connlimit_Match,
CONNMARK => \&Connmark,
@@ -2853,6 +2860,7 @@ sub determine_capabilities() {
$capabilities{ACCOUNT_TARGET} = detect_capability( 'ACCOUNT_TARGET' );
$capabilities{AUDIT_TARGET} = detect_capability( 'AUDIT_TARGET' );
$capabilities{IPSET_V5} = detect_capability( 'IPSET_V5' );
+ $capabilities{CONDITION_MATCH} = detect_capability( 'CONDITION_MATCH' );
qt1( "$iptables -F $sillyname" );
diff --git a/Shorewall/Perl/Shorewall/Rules.pm b/Shorewall/Perl/Shorewall/Rules.pm
index 1de930d26..fee53ca9d 100644
--- a/Shorewall/Perl/Shorewall/Rules.pm
+++ b/Shorewall/Perl/Shorewall/Rules.pm
@@ -1382,7 +1382,7 @@ sub process_actions() {
}
-sub process_rule1 ( $$$$$$$$$$$$$$$$ );
+sub process_rule1 ( $$$$$$$$$$$$$$$$$ );
#
# Populate an action invocation chain. As new action tuples are encountered,
@@ -1415,14 +1415,14 @@ sub process_action( $) {
while ( read_a_line ) {
- my ($target, $source, $dest, $proto, $ports, $sports, $origdest, $rate, $user, $mark, $connlimit, $time, $headers );
+ 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;
- $origdest = $connlimit = $time = $headers = '-';
+ $origdest = $connlimit = $time = $headers = $condition = '-';
} else {
- ($target, $source, $dest, $proto, $ports, $sports, $origdest, $rate, $user, $mark, $connlimit, $time, $headers )
- = split_line1 1, 13, 'action file', $action_commands;
+ ($target, $source, $dest, $proto, $ports, $sports, $origdest, $rate, $user, $mark, $connlimit, $time, $headers, $condition )
+ = split_line1 1, 14, 'action file', $action_commands;
}
if ( $target eq 'COMMENT' ) {
@@ -1456,6 +1456,7 @@ sub process_action( $) {
$connlimit,
$time,
$headers,
+ $condition,
0 );
}
@@ -1485,8 +1486,8 @@ sub use_policy_action( $ ) {
#
# Expand a macro rule from the rules file
#
-sub process_macro ( $$$$$$$$$$$$$$$$$ ) {
- my ($macro, $chainref, $target, $param, $source, $dest, $proto, $ports, $sports, $origdest, $rate, $user, $mark, $connlimit, $time, $headers, $wildcard ) = @_;
+sub process_macro ( $$$$$$$$$$$$$$$$$$ ) {
+ my ($macro, $chainref, $target, $param, $source, $dest, $proto, $ports, $sports, $origdest, $rate, $user, $mark, $connlimit, $time, $headers, $condition, $wildcard ) = @_;
my $nocomment = no_comment;
@@ -1504,13 +1505,13 @@ sub process_macro ( $$$$$$$$$$$$$$$$$ ) {
while ( read_a_line ) {
- my ( $mtarget, $msource, $mdest, $mproto, $mports, $msports, $morigdest, $mrate, $muser, $mmark, $mconnlimit, $mtime, $mheaders );
+ 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;
- ( $morigdest, $mmark, $mconnlimit, $mtime, $mheaders ) = qw/- - - - -/;
+ ( $morigdest, $mmark, $mconnlimit, $mtime, $mheaders, $mcondition ) = qw/- - - - - -/;
} else {
- ( $mtarget, $msource, $mdest, $mproto, $mports, $msports, $morigdest, $mrate, $muser, $mmark, $mconnlimit, $mtime, $mheaders ) = split_line1 1, 13, 'macro file', $rule_commands;
+ ( $mtarget, $msource, $mdest, $mproto, $mports, $msports, $morigdest, $mrate, $muser, $mmark, $mconnlimit, $mtime, $mheaders, $mcondition ) = split_line1 1, 14, 'macro file', $rule_commands;
}
if ( $mtarget eq 'COMMENT' ) {
@@ -1586,6 +1587,7 @@ sub process_macro ( $$$$$$$$$$$$$$$$$ ) {
merge_macro_column( $mconnlimit, $connlimit) ,
merge_macro_column( $mtime, $time ),
merge_macro_column( $mheaders, $headers ),
+ merge_macro_column( $mcondition, $condition ),
$wildcard
);
@@ -1618,7 +1620,7 @@ sub verify_audit($;$$) {
# Similarly, if a new action tuple is encountered, this function is called recursively for each rule in the action
# body. In this latter case, a reference to the tuple's chain is passed in the first ($chainref) argument.
#
-sub process_rule1 ( $$$$$$$$$$$$$$$$ ) {
+sub process_rule1 ( $$$$$$$$$$$$$$$$ $) {
my ( $chainref, #reference to Action Chain if we are being called from process_action(); undef otherwise
$target,
$current_param,
@@ -1634,6 +1636,7 @@ sub process_rule1 ( $$$$$$$$$$$$$$$$ ) {
$connlimit,
$time,
$headers,
+ $condition,
$wildcard ) = @_;
my ( $action, $loglevel) = split_action $target;
@@ -1685,6 +1688,7 @@ sub process_rule1 ( $$$$$$$$$$$$$$$$ ) {
$connlimit,
$time,
$headers,
+ $condition,
$wildcard );
$macro_nest_level--;
@@ -1925,6 +1929,7 @@ sub process_rule1 ( $$$$$$$$$$$$$$$$ ) {
do_connlimit( $connlimit ),
do_time( $time ) ,
do_headers( $headers ) ,
+ do_condition( $condition ) ,
);
} else {
$rule = join( '',
@@ -1934,7 +1939,8 @@ sub process_rule1 ( $$$$$$$$$$$$$$$$ ) {
do_test( $mark , $globals{TC_MASK} ) ,
do_connlimit( $connlimit ),
do_time( $time ) ,
- do_headers( $headers )
+ do_headers( $headers ) ,
+ do_condition( $condition ) ,
);
}
@@ -2313,8 +2319,8 @@ sub build_zone_list( $$$\$\$ ) {
# Process a Record in the rules file
#
sub process_rule ( ) {
- my ( $target, $source, $dest, $protos, $ports, $sports, $origdest, $ratelimit, $user, $mark, $connlimit, $time, $headers )
- = split_line1 1, 13, 'rules file', $rule_commands;
+ my ( $target, $source, $dest, $protos, $ports, $sports, $origdest, $ratelimit, $user, $mark, $connlimit, $time, $headers, $condition )
+ = split_line1 1, 14, 'rules file', $rule_commands;
process_comment, return 1 if $target eq 'COMMENT';
process_section( $source ), return 1 if $target eq 'SECTION';
@@ -2367,6 +2373,7 @@ sub process_rule ( ) {
$connlimit,
$time,
$headers,
+ $condition,
$wild );
}
}
diff --git a/Shorewall/configfiles/rules b/Shorewall/configfiles/rules
index 79fae68cf..068b23ff9 100644
--- a/Shorewall/configfiles/rules
+++ b/Shorewall/configfiles/rules
@@ -6,8 +6,8 @@
# The manpage is also online at
# http://www.shorewall.net/manpages/shorewall-rules.html
#
-####################################################################################################################################################################
-#ACTION SOURCE DEST PROTO DEST SOURCE ORIGINAL RATE USER/ MARK CONNLIMIT TIME HEADERS
+######################################################################################################################################################################################
+#ACTION SOURCE DEST PROTO DEST SOURCE ORIGINAL RATE USER/ MARK CONNLIMIT TIME HEADERS CONDITION
# PORT PORT(S) DEST LIMIT GROUP
#SECTION ALL
#SECTION ESTABLISHED
diff --git a/Shorewall/lib.base b/Shorewall/lib.base
index e23414417..cae2fdb9e 100644
--- a/Shorewall/lib.base
+++ b/Shorewall/lib.base
@@ -28,7 +28,7 @@
#
SHOREWALL_LIBVERSION=40407
-SHOREWALL_CAPVERSION=40421
+SHOREWALL_CAPVERSION=40424
[ -n "${VARDIR:=/var/lib/shorewall}" ]
[ -n "${SHAREDIR:=/usr/share/shorewall}" ]
diff --git a/Shorewall/lib.cli b/Shorewall/lib.cli
index a669db3c0..a3356e2db 100644
--- a/Shorewall/lib.cli
+++ b/Shorewall/lib.cli
@@ -1731,6 +1731,7 @@ determine_capabilities() {
HEADER_MATCH=
ACCOUNT_TARGET=
AUDIT_TARGET=
+ CONDITION_MATCH=
chain=fooX$$
@@ -1881,6 +1882,7 @@ determine_capabilities() {
qt $IPTABLES -A $chain -j MARK --set-mark 5 && MARK_ANYWHERE=Yes
qt $IPTABLES -A $chain -j ACCOUNT --addr 192.168.1.0/29 --tname $chain && ACCOUNT_TARGET=Yes
qt $IPTABLES -A $chain -j AUDIT --type drop && AUDIT_TARGET=Yes
+ qt $IPTABLES -A $chain -m condition --condition foo && CONDITION_MATCH=Yes
qt $IPTABLES -F $chain
qt $IPTABLES -X $chain
qt $IPTABLES -F $chain1
@@ -1975,6 +1977,7 @@ report_capabilities() {
report_capability "ACCOUNT Target" $ACCOUNT_TARGET
report_capability "AUDIT Target" $AUDIT_TARGET
report_capability "ipset V5" $IPSET_V5
+ report_capability "Condition Match" $CONDITION_MATCH
fi
[ -n "$PKTTYPE" ] || USEPKTTYPE=
@@ -2045,6 +2048,7 @@ report_capabilities1() {
report_capability1 ACCOUNT_TARGET
report_capability1 AUDIT_TARGET
report_capability1 IPSET_V5
+ report_capability1 CONDITION_MATCH
echo CAPVERSION=$SHOREWALL_CAPVERSION
echo KERNELVERSION=$KERNELVERSION
diff --git a/Shorewall6/lib.base b/Shorewall6/lib.base
index a4dcae25c..76d1422f1 100644
--- a/Shorewall6/lib.base
+++ b/Shorewall6/lib.base
@@ -32,7 +32,7 @@
#
SHOREWALL_LIBVERSION=40407
-SHOREWALL_CAPVERSION=40423
+SHOREWALL_CAPVERSION=40424
[ -n "${VARDIR:=/var/lib/shorewall6}" ]
[ -n "${SHAREDIR:=/usr/share/shorewall6}" ]
diff --git a/Shorewall6/lib.cli b/Shorewall6/lib.cli
index 8fc9f5113..6b4848b22 100644
--- a/Shorewall6/lib.cli
+++ b/Shorewall6/lib.cli
@@ -1558,6 +1558,7 @@ determine_capabilities() {
ACCOUNT_TARGET=
AUDIT_TARGET=
IPSET_V5=
+ CONDITION_MATCH=
chain=fooX$$
@@ -1709,6 +1710,7 @@ determine_capabilities() {
qt $IP6TABLES -A $chain -m ipv6header --header 255 && HEADER_MATCH=Yes
qt $IP6TABLES -A $chain -j ACCOUNT --addr 1::/122 --tname $chain && ACCOUNT_TARGET=Yes
qt $IP6TABLES -A $chain -j AUDIT --type drop && AUDIT_TARGET=Yes
+ qt $IP6TABLES -A $chain -m condition --condition foo && CONDITION_MATCH=Yes
qt $IP6TABLES -F $chain
@@ -1802,6 +1804,7 @@ report_capabilities() {
report_capability "ACCOUNT Target" $ACCOUNT_TARGET
report_capability "AUDIT Target" $AUDIT_TARGET
report_capability "ipset V5" $IPSET_V5
+ report_capability "Condition Match" $CONDITION_MATCH
fi
[ -n "$PKTTYPE" ] || USEPKTTYPE=
@@ -1869,6 +1872,7 @@ report_capabilities1() {
report_capability1 ACCOUNT_TARGET
report_capability1 AUDIT_TARGET
report_capability1 IPSET_V5
+ report_capability1 CONDITION_MATCH
echo CAPVERSION=$SHOREWALL_CAPVERSION
echo KERNELVERSION=$KERNELVERSION
diff --git a/manpages/shorewall-rules.xml b/manpages/shorewall-rules.xml
index aa46d1e67..6009b4d4d 100644
--- a/manpages/shorewall-rules.xml
+++ b/manpages/shorewall-rules.xml
@@ -1267,6 +1267,30 @@
+
+
+ HEADERS
+
+
+ Added in Shorewall 4.4.15. Not used in IPv4 configurations. If
+ you with to supply a value for one of the later columns, enter '-'
+ in this column.
+
+
+
+
+ CONDITION -
+ [!]condition-name
+
+
+ Added in Shorewall 4.4.24. Matches if the value stored in
+ /proc/net/nf_condition/condition-name
+ is 1. Does not match if that file contains 0 (the default). If '!'
+ is supplied, the test is inverted such that there is a match if the
+ file contains 0. The condition-name must begin with a letter and be
+ composed of letters, decimal digits or underscores.
+
+
@@ -1457,6 +1481,19 @@
SSH(ACCEPT) net all - - - - s:1/min:3
+
+
+ Example 12:
+
+
+ Forward port 80 to dmz host $BACKUP if condition
+ 'primary_down' is set.
+
+ #ACTION SOURCE DEST PROTO DEST SOURCE ORIGINAL RATE USER/ MARK CONNLIMIT TIME HEADERS CONDITION
+ # PORT(S) PORT(S) DEST LIMIT GROUP
+ DNAT net dmz:$BACKUP tcp 80 - - - - - - - - primary_down
+
+
diff --git a/manpages6/shorewall6-rules.xml b/manpages6/shorewall6-rules.xml
index 11ff82842..ecebf06bf 100644
--- a/manpages6/shorewall6-rules.xml
+++ b/manpages6/shorewall6-rules.xml
@@ -1102,6 +1102,20 @@
role="bold">! is omitted.
+
+
+ CONDITION -
+ [!]condition-name
+
+
+ Added in Shorewall6 4.4.24. Matches if the value stored in
+ /proc/net/nf_condition/condition-name
+ is 1. Does not match if that file contains 0 (the default). If '!'
+ is supplied, the test is inverted such that there is a match if the
+ file contains 0. The condition-name must begin with a letter and be
+ composed of letters, decimal digits or underscores.
+
+
@@ -1148,6 +1162,19 @@
SSH(ACCEPT) net all - - - - s:1/min:3
+
+
+ Example 6:
+
+
+ Forward port 80 to dmz host $BACKUP if condition
+ 'primary_down' is set.
+
+ #ACTION SOURCE DEST PROTO DEST SOURCE ORIGINAL RATE USER/ MARK CONNLIMIT TIME HEADERS CONDITION
+ # PORT(S) PORT(S) DEST LIMIT GROUP
+ DNAT net dmz:$BACKUP tcp 80 - - - - - - - - primary_down
+
+
@@ -1162,8 +1189,8 @@
shorewall6(8), shorewall6-accounting(5), shorewall6-actions(5),
shorewall6-blacklist(5), shorewall6-hosts(5), shorewall6-interfaces(5),
- shorewall6-maclist(5), shoewall6-netmap(5),shorewall6-params(5), shorewall6-policy(5),
- shorewall6-providers(5), shorewall6-route_rules(5),
+ shorewall6-maclist(5), shoewall6-netmap(5),shorewall6-params(5),
+ shorewall6-policy(5), shorewall6-providers(5), shorewall6-route_rules(5),
shorewall6-routestopped(5), shorewall6.conf(5), shorewall6-secmarks(5),
shorewall6-tcclasses(5), shorewall6-tcdevices(5), shorewall6-tcrules(5),
shorewall6-tos(5), shorewall6-tunnels(5), shorewall6-zones(5)