diff --git a/Shorewall/Perl/Shorewall/Config.pm b/Shorewall/Perl/Shorewall/Config.pm
index 60a5951ef..332cc3d34 100644
--- a/Shorewall/Perl/Shorewall/Config.pm
+++ b/Shorewall/Perl/Shorewall/Config.pm
@@ -130,6 +130,7 @@ our %EXPORT_TAGS = ( internal => [ qw( create_temp_script
split_list
split_list1
split_list2
+ split_list3
split_line
split_line1
split_line2
diff --git a/Shorewall/Perl/Shorewall/Rules.pm b/Shorewall/Perl/Shorewall/Rules.pm
index f60037809..5cdfe174b 100644
--- a/Shorewall/Perl/Shorewall/Rules.pm
+++ b/Shorewall/Perl/Shorewall/Rules.pm
@@ -2748,6 +2748,11 @@ sub process_rule ( $$$$$$$$$$$$$$$$$$$$ ) {
fatal_error "Unknown ACTION ($action)" unless $actiontype;
$usergenerated = $actiontype & IPTABLES;
+ #
+ # For now, we'll just strip the parens from the SOURCE and DEST. In a later release, we might be able to do something more with them
+ #
+ $source =~ s/[()]//g;
+ $dest =~ s/[()]//g;
if ( $actiontype == MACRO ) {
#
@@ -3777,22 +3782,8 @@ sub build_zone_list( $$$\$\$ ) {
#
# Process a Record in the rules file
#
-sub process_raw_rule ( ) {
- my ( $target, $source, $dest, $protos, $ports, $sports, $origdest, $ratelimit, $users, $mark, $connlimit, $time, $headers, $condition, $helper )
- = split_line2( 'rules file',
- \%rulecolumns,
- $rule_commands,
- undef, #Columns
- 1 ); #Allow inline matches
-
-
- fatal_error 'ACTION must be specified' if $target eq '-';
- #
- # Section Names are optional so once we get to an actual rule, we need to be sure that
- # we close off any missing sections.
- #
- next_section if $section != $next_section;
-
+sub process_raw_rule1( $$$$$$$$$$$$$$$ ) {
+ my ( $target, $source, $dest, $protos, $ports, $sports, $origdest, $ratelimit, $users, $mark, $connlimit, $time, $headers, $condition, $helper ) = @_;
if ( $source =~ /^none(:.*)?$/i || $dest =~ /^none(:.*)?$/i ) {
progress_message "Rule \"$currentline\" ignored.";
return 1;
@@ -3858,6 +3849,44 @@ sub process_raw_rule ( ) {
progress_message qq( Rule "$thisline" $done);
}
+sub process_raw_rule ( ) {
+ my ( $target, $source, $dest, $protos, $ports, $sports, $origdest, $ratelimit, $users, $mark, $connlimit, $time, $headers, $condition, $helper )
+ = split_line2( 'rules file',
+ \%rulecolumns,
+ $rule_commands,
+ undef, #Columns
+ 1 ); #Allow inline matches
+
+
+ fatal_error 'ACTION must be specified' if $target eq '-';
+ #
+ # Section Names are optional so once we get to an actual rule, we need to be sure that
+ # we close off any missing sections.
+ #
+ next_section if $section != $next_section;
+
+ my ( @source, @dest );
+
+ if ( $source =~ /:\(.+\)/ ) {
+ @source = split_list3( $source, 'SOURCE' );
+ } else {
+ @source = ( $source );
+ }
+
+ if ( $dest =~ /:\(.+\)/ ) {
+ @dest = split_list3( $dest, 'DEST' );
+ } else {
+ @dest = ( $dest );
+ }
+
+ for $source ( @source ) {
+ for $dest ( @dest ) {
+ process_raw_rule1( $target, $source, $dest, $protos, $ports, $sports, $origdest, $ratelimit, $users, $mark, $connlimit, $time, $headers, $condition, $helper );
+ }
+ }
+}
+
+
sub intrazone_allowed( $$ ) {
my ( $zone, $zoneref ) = @_;
diff --git a/Shorewall/manpages/shorewall-rules.xml b/Shorewall/manpages/shorewall-rules.xml
index c411ab59d..01daa2774 100644
--- a/Shorewall/manpages/shorewall-rules.xml
+++ b/Shorewall/manpages/shorewall-rules.xml
@@ -907,8 +907,8 @@
role="bold">+][-]}[:interface][:{address-or-range[,address-or-range]...[exclusion]|exclusion|+ipset|^countrycode-list}
+ role="bold">:[(]{address-or-range[,address-or-range]...[exclusion]|exclusion|+ipset|^countrycode-list}[)][,...]
Source hosts to which the rule applies. May be a
@@ -1093,6 +1093,26 @@
+
+ Beginning with Shorewall 5.1.0, multiple
+ zone:[interface:](address-list)
+ tupples can be listed, separated by commas. Where the
+ address-list consists of more than a
+ single address, the list must be enclosed in parentheses.
+
+ Example:
+
+
+
+ dmz:(192.168.2.2,192.168.2.3),net:(206.124.146.22,155.186.235.0/24!155.186.235.16/28)
+
+
+ Hosts 192.168.2.2 and 192.168.2.3 in the dmz zone, host
+ 206.124.146.22 in the dmz zone and network 155.186.235.0/24 in
+ the net zone excluding 155.186.235.16/28.
+
+
+
@@ -1103,7 +1123,7 @@
role="bold">any}[+][-]}[:{interface|address-or-range[,address-or-range]...[exclusion]|exclusion|[:{interface|[(]address-or-range[,address-or-range]...[exclusion][)]|[(]exclusion[)]|+ipset|^countrycode-list}][port[:random]]
@@ -1270,6 +1290,13 @@
the port number on the firewall that the request should be
redirected to. That is equivalent to specifying
::port.
+
+ Beginning with Shorewall 5.1.0, multiple
+ zone:[interface:](address-list)
+ tupples can be listed, separated by commas. Where the
+ address-list consists of more than a
+ single address, the list must be enclosed in parentheses. See the
+ example in the SOURCE section above.
diff --git a/Shorewall6/manpages/shorewall6-rules.xml b/Shorewall6/manpages/shorewall6-rules.xml
index e351f58d6..88a0189ce 100644
--- a/Shorewall6/manpages/shorewall6-rules.xml
+++ b/Shorewall6/manpages/shorewall6-rules.xml
@@ -866,9 +866,9 @@
role="bold">{all|any}[+][-]}[:interface][[:interface][(][:{address-or-range[,address-or-range]...[exclusion]|exclusion|+ipset|^countrycode-list}
+ role="bold">+ipset|^countrycode-list}[)][,...]
Source hosts to which the rule applies. May be a zone declared
@@ -960,7 +960,7 @@
- dmz:2002:ce7c::92b4:1::2
+ dmz:[2002:ce7c:2b4:1::2]Host 2002:ce7c:92b4:1::2 in the DMZ
@@ -976,7 +976,7 @@
- loc:<2002:cec792b4:1::2,2002:cec792b4:1::44>
+ loc:[2002:cec792b4:1::2],[2002:cec792b4:1::44]Hosts 2002:cec792b4:1::2 and 2002:cec792b4:1::44 in the
@@ -994,11 +994,11 @@
- net:2001:4d48:ad51:24::/64!2001:4d48:ad51:24:6:/80!2001:4d48:ad51:24:6:/80
+ net:[2001:4d48:ad51:24::]/64![2001:4d48:ad51:24:6::]/80Subnet 2001:4d48:ad51:24::/64 on the Internet except for
- 2001:4d48:ad51:24:6:/80.
+ 2001:4d48:ad51:24:6::/80.
@@ -1024,7 +1024,7 @@
- loc:eth1:<2002:cec792b4:1::2,2002:cec792b4:1::44>
+ loc:eth1:[2002:cec792b4:1::2],[2002:cec792b4:1::44]Hosts 2002:cec792b4:1::2 and 2002:cec792b4:1::44 in the
@@ -1033,6 +1033,26 @@
+
+ Beginning with Shorewall 5.1.0, multiple
+ zone:[interface:](address-list)
+ tupples can be listed, separated by commas. Where the
+ address-list consists of more than a
+ single address, the list must be enclosed in parentheses.
+
+ Example:
+
+
+
+ dmz:([2002:c37c:92b4:1::2],[2002:c37c:92b4:1::3]),loc:eth1:([2002:cec792b4:1::2],[2002:cec792b4:1::44])
+
+
+ Hosts 2002:c37c:92b4:1::2 and 2002:c37c:92b4:1::3 in the
+ dmz zone and hosts 2002:cec792b4:1::2 and 2002:cec792b4:1::44
+ in the loc zone via interface eth1
+
+
+