From 375b2007fd32868e21a10f96eaffbbc3348a3961 Mon Sep 17 00:00:00 2001
From: teastep <teastep@fbd18981-670d-0410-9b5c-8dc0c1a9a2bb>
Date: Sun, 10 Sep 2006 17:22:02 +0000
Subject: [PATCH] Fix tos file handling of zones defined via
 /etc/shorewall/hosts

git-svn-id: https://shorewall.svn.sourceforge.net/svnroot/shorewall/trunk@4560 fbd18981-670d-0410-9b5c-8dc0c1a9a2bb
---
 Shorewall/compiler   |  18 ++--
 Shorewall/lib.config | 228 ++++++++++++++++++++++++-------------------
 2 files changed, 134 insertions(+), 112 deletions(-)

diff --git a/Shorewall/compiler b/Shorewall/compiler
index e97055370..437964eda 100755
--- a/Shorewall/compiler
+++ b/Shorewall/compiler
@@ -2300,18 +2300,14 @@ process_rule() # $1 = target
 
     validate_zone $clientzone || fatal_error "Undefined Client Zone in rule \"$rule\""
 
-    # Parse and validate destination
-
     source=$clientzone
 
-    if [ $source = $FW ]; then
-	source_hosts=
-    elif [ -n "$userspec" ]; then
+    if [ $source != $FW -a -n "$userspec" ]; then
 	fatal_error "Invalid use of a user-qualification: rule \"$rule\""
-    else
-	eval source_hosts=\"\$${source}_hosts\"
     fi
 
+    # Parse and validate destination
+
     if [ "$servers" = "${servers%:*}" ] ; then
 	serverzone="$servers"
 	servers=
@@ -3021,7 +3017,7 @@ process_tos_rule() {
     esac
 
     for dest in $dst; do
-	dest="$(dest_ip_range $dest)"
+	dest=$(match_dest $dest)
 
 	case $srczone in
 	$FW)
@@ -3039,10 +3035,10 @@ process_tos_rule() {
 		run_iptables2 -t mangle -A pretos $src \
 		    $protocol $dest $dports $sports $tos
 	    else
-		eval interfaces=\$${srczone}_interfaces
+		eval hosts=\$${srczone}_hosts
 
-		for interface in $interfaces; do
-		    run_iptables2 -t mangle -A pretos -i $interface \
+		for host in $hosts; do
+		    run_iptables2 -t mangle -A pretos $(match_source $host) \
 			$protocol $dest $dports $sports $tos
 		done
 	    fi
diff --git a/Shorewall/lib.config b/Shorewall/lib.config
index cab5147b6..f83fca983 100644
--- a/Shorewall/lib.config
+++ b/Shorewall/lib.config
@@ -591,7 +591,7 @@ validate_hosts_file() {
 		       ;;
 		   *.*.*)
 		       ;;
-		   *+|+*)
+		   *+|+*|*!*)
 		       eval ${z}_is_complex=Yes
 		       ;;
 		   *)
@@ -604,7 +604,7 @@ validate_hosts_file() {
 	       case $host in
 		   *.*.*)
 		       ;;
-		   *+)
+		   *+|*!*)
 		       eval ${z}_is_complex=Yes
 		       ;;
 		   *)
@@ -827,6 +827,105 @@ physdev_echo()
     fi
 }
 
+#
+# Source IP range
+#
+source_ip_range() # $1 = Address or Address Range
+{
+    [ $# -gt 0 ] && case $1 in
+	*.*.*.*-*.*.*.*)
+	    case $1 in
+		!*)
+		    iprange_echo "! --src-range ${1#!}"
+		    ;;
+		*)
+		    iprange_echo "--src-range $1"
+		    ;;
+	    esac
+	    ;;
+	!+*)
+	    echo "-m set ! $(get_set_flags ${1#!} src)"
+	    ;;
+	+*)
+	    echo "-m set $(get_set_flags $1 src)"
+	    ;;
+	*)
+	    echo "-s $1"
+	    ;;
+    esac
+}
+
+#
+# Destination IP range
+#
+dest_ip_range() # $1 = Address or Address Range
+{
+    [ $# -gt 0 ] && case $1 in
+	*.*.*.*-*.*.*.*)
+	    case $1 in
+		!*)
+		    iprange_echo "! --dst-range ${1#!}"
+		    ;;
+		*)
+		    iprange_echo "--dst-range $1"
+		    ;;
+	    esac
+	    ;;
+	!+*)
+	    echo "-m set ! $(get_set_flags ${1#!} dst)"
+	    ;;
+	+*)
+	    echo "-m set $(get_set_flags $1 dst)"
+	    ;;
+	*)
+	    echo "-d $1"
+	    ;;
+    esac
+}
+
+both_ip_ranges() # $1 = Source address or range, $2 = dest address or range
+{
+    local rangeprefix= setprefix= rangematch= setmatch=
+
+    case $1 in
+	*.*.*.*-*.*.*.*)
+	    rangeprefix="-m iprange"
+	    rangematch="--src-range $1"
+	    ;;
+	!+*)
+	    setprefix="-m set"
+	    setmatch="! $(get_set_flags ${1#!} src)"
+	    ;;
+	+*)
+	    setprefix="-m set"
+	    setmatch="$(get_set_flags $1 src)"
+	    ;;
+	*)
+	    rangematch="-s $1"
+	    ;;
+    esac
+
+    case $2 in
+	*.*.*.*-*.*.*.*)
+	    rangeprefix="-m iprange"
+	    rangematch="$rangematch --dst-range $2"
+	    ;;
+	!+*)
+	    setprefix="-m set"
+	    match="$setmatch ! $(get_set_flags ${2#!} dst)"
+	    ;;
+	+*)
+	    setprefix="-m set"
+	    setmatch="$setmatch $(get_set_flags $2 dst)"
+	    ;;
+	*)
+	    rangematch="$rangematch -d $2"
+	    ;;
+    esac
+
+    echo "$rangeprefix $rangematch $setprefix $setmatch"
+}
+
 #
 # We allow hosts to be specified by IP address or by physdev. These two functions
 # are used to produce the proper match in a netfilter rule.
@@ -868,6 +967,32 @@ match_dest_hosts()
 	echo $(dest_ip_range $1)
     fi
 }
+#
+# Matches for either <address-range> or <interface>:<address range>
+#
+match_source() 
+{
+    case "$1" in
+	*:*)
+	    echo "-i ${1%%:*} $(match_source_hosts ${1#*:})"
+	    ;;
+	*)
+	    echo $(dest_ip_range $1)
+	    ;;
+    esac
+}
+
+match_dest()
+{
+    case "$1" in
+	*:*)
+	    echo "-o ${1%%:*} $(match_dest_hosts ${1#*:})"
+	    ;;
+	*)
+	    echo $(dest_ip_range $1)
+	    ;;
+    esac
+}
 
 #
 # Similarly, the source or destination in a rule can be qualified by a device name. If
@@ -1447,105 +1572,6 @@ strip_file_and_lib_load() # $1 = logical file name, $2 = library to load if the
     eval test -n \"\$LIB_${2}_LOADED\"
 }
 
-#
-# Source IP range
-#
-source_ip_range() # $1 = Address or Address Range
-{
-    [ $# -gt 0 ] && case $1 in
-	*.*.*.*-*.*.*.*)
-	    case $1 in
-		!*)
-		    iprange_echo "! --src-range ${1#!}"
-		    ;;
-		*)
-		    iprange_echo "--src-range $1"
-		    ;;
-	    esac
-	    ;;
-	!+*)
-	    echo "-m set ! $(get_set_flags ${1#!} src)"
-	    ;;
-	+*)
-	    echo "-m set $(get_set_flags $1 src)"
-	    ;;
-	*)
-	    echo "-s $1"
-	    ;;
-    esac
-}
-
-#
-# Destination IP range
-#
-dest_ip_range() # $1 = Address or Address Range
-{
-    [ $# -gt 0 ] && case $1 in
-	*.*.*.*-*.*.*.*)
-	    case $1 in
-		!*)
-		    iprange_echo "! --dst-range ${1#!}"
-		    ;;
-		*)
-		    iprange_echo "--dst-range $1"
-		    ;;
-	    esac
-	    ;;
-	!+*)
-	    echo "-m set ! $(get_set_flags ${1#!} dst)"
-	    ;;
-	+*)
-	    echo "-m set $(get_set_flags $1 dst)"
-	    ;;
-	*)
-	    echo "-d $1"
-	    ;;
-    esac
-}
-
-both_ip_ranges() # $1 = Source address or range, $2 = dest address or range
-{
-    local rangeprefix= setprefix= rangematch= setmatch=
-
-    case $1 in
-	*.*.*.*-*.*.*.*)
-	    rangeprefix="-m iprange"
-	    rangematch="--src-range $1"
-	    ;;
-	!+*)
-	    setprefix="-m set"
-	    setmatch="! $(get_set_flags ${1#!} src)"
-	    ;;
-	+*)
-	    setprefix="-m set"
-	    setmatch="$(get_set_flags $1 src)"
-	    ;;
-	*)
-	    rangematch="-s $1"
-	    ;;
-    esac
-
-    case $2 in
-	*.*.*.*-*.*.*.*)
-	    rangeprefix="-m iprange"
-	    rangematch="$rangematch --dst-range $2"
-	    ;;
-	!+*)
-	    setprefix="-m set"
-	    match="$setmatch ! $(get_set_flags ${2#!} dst)"
-	    ;;
-	+*)
-	    setprefix="-m set"
-	    setmatch="$setmatch $(get_set_flags $2 dst)"
-	    ;;
-	*)
-	    rangematch="$rangematch -d $2"
-	    ;;
-    esac
-
-    echo "$rangeprefix $rangematch $setprefix $setmatch"
-}
-
 #
 # Check that a mark value or mask is less that 256 or that it is less than 65536 and
 # that it's lower 8 bits are zero.