From: Jo-Philipp Wich <jow@openwrt.org>
Date: Wed, 19 May 2010 21:35:23 +0000 (+0000)
Subject: firewall: - fix ip6tables rules when icmp_type option is set - add "family" option... 
X-Git-Url: http://git.cdn.openwrt.org/?a=commitdiff_plain;h=40ad9defcc545c2925f6c37d17a64707f17f5b78;p=openwrt%2Fstaging%2Fynezz.git

firewall: - fix ip6tables rules when icmp_type option is set - add "family" option to zones, forwardings, redirects and rules to selectively apply rules to iptables and/or ip6tables

SVN-Revision: 21508
---

diff --git a/package/firewall/Makefile b/package/firewall/Makefile
index 1a7216ce17..4f4f71c325 100644
--- a/package/firewall/Makefile
+++ b/package/firewall/Makefile
@@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
 PKG_NAME:=firewall
 
 PKG_VERSION:=2
-PKG_RELEASE:=3
+PKG_RELEASE:=4
 
 include $(INCLUDE_DIR)/package.mk
 
diff --git a/package/firewall/files/lib/core_forwarding.sh b/package/firewall/files/lib/core_forwarding.sh
index 766e48e38e..689e2628c2 100644
--- a/package/firewall/files/lib/core_forwarding.sh
+++ b/package/firewall/files/lib/core_forwarding.sh
@@ -7,6 +7,7 @@ fw_config_get_forwarding() {
 		string name "" \
 		string src "" \
 		string dest "" \
+		string family "" \
 	} || return
 	[ -n "$forwarding_name" ] || forwarding_name=$forwarding__name
 }
@@ -26,7 +27,9 @@ fw_load_forwarding() {
 		target=zone_${forwarding_dest}_ACCEPT
 	}
 
-	fw add i f $chain $target ^
+	local mode=$(fw_get_family_mode ${forwarding_family:-x} ${forwarding_dest:-${forwarding_src:--}} i)
+
+	fw add $mode f $chain $target ^
 
 	# propagate masq zone flag
 	[ -n "$forwarding_src" ] && list_contains CONNTRACK_ZONES $forwarding_src && {
diff --git a/package/firewall/files/lib/core_init.sh b/package/firewall/files/lib/core_init.sh
index 2dd989e494..92d117160f 100644
--- a/package/firewall/files/lib/core_init.sh
+++ b/package/firewall/files/lib/core_init.sh
@@ -4,6 +4,8 @@
 FW_INITIALIZED=
 
 FW_ZONES=
+FW_ZONES4=
+FW_ZONES6=
 FW_CONNTRACK_ZONES=
 FW_NOTRACK_DISABLED=
 
@@ -140,6 +142,7 @@ fw_config_get_zone() {
 		boolean conntrack 0 \
 		boolean mtu_fix 0 \
 		boolean custom_chains "$FW_ADD_CUSTOM_CHAINS" \
+		string family "" \
 	} || return
 	[ -n "$zone_name" ] || zone_name=$zone_NAME
 	[ -n "$zone_network" ] || zone_network=$zone_name
@@ -158,46 +161,67 @@ fw_load_zone() {
 	[ $zone_conntrack = 1 -o $zone_masq = 1 ] && \
 		append FW_CONNTRACK_ZONES "$zone_NAME"
 
+	local mode
+	case "$zone_family" in
+		*4)
+			mode=4
+			append FW_ZONES4 $zone_name
+			uci_set_state firewall core ${zone_name}_ipv4 1
+		;;
+		*6)
+			mode=6
+			append FW_ZONES6 $zone_name
+			uci_set_state firewall core ${zone_name}_ipv6 1
+		;;
+		*)
+			mode=i
+			append FW_ZONES4 $zone_name
+			append FW_ZONES6 $zone_name
+			uci_set_state firewall core ${zone_name}_ipv4 1
+			uci_set_state firewall core ${zone_name}_ipv6 1
+		;;
+	esac
+
 	local chain=zone_${zone_name}
 
-	fw add i f ${chain}_ACCEPT
-	fw add i f ${chain}_DROP
-	fw add i f ${chain}_REJECT
-	fw add i f ${chain}_MSSFIX
+	fw add $mode f ${chain}_ACCEPT
+	fw add $mode f ${chain}_DROP
+	fw add $mode f ${chain}_REJECT
+	fw add $mode f ${chain}_MSSFIX
 
 	# TODO: Rename to ${chain}_input
-	fw add i f ${chain}
-	fw add i f ${chain} ${chain}_${zone_input} $
+	fw add $mode f ${chain}
+	fw add $mode f ${chain} ${chain}_${zone_input} $
 
-	fw add i f ${chain}_forward
-	fw add i f ${chain}_forward ${chain}_${zone_forward} $
+	fw add $mode f ${chain}_forward
+	fw add $mode f ${chain}_forward ${chain}_${zone_forward} $
 
 	# TODO: add ${chain}_output
-	fw add i f output ${chain}_${zone_output} $
+	fw add $mode f output ${chain}_${zone_output} $
 
 	# TODO: Rename to ${chain}_MASQUERADE
-	fw add i n ${chain}_nat
-	fw add i n ${chain}_prerouting
+	fw add $mode n ${chain}_nat
+	fw add $mode n ${chain}_prerouting
 
-	fw add i r ${chain}_notrack
+	fw add $mode r ${chain}_notrack
 	[ $zone_masq == 1 ] && \
-		fw add i n POSTROUTING ${chain}_nat $
+		fw add $mode n POSTROUTING ${chain}_nat $
 
 	[ $zone_mtu_fix == 1 ] && \
-		fw add i f FORWARD ${chain}_MSSFIX ^
+		fw add $mode f FORWARD ${chain}_MSSFIX ^
 
 	[ $zone_custom_chains == 1 ] && {
 		[ $FW_ADD_CUSTOM_CHAINS == 1 ] || \
 			fw_die "zone ${zone_name}: custom_chains globally disabled"
 
-		fw add i f input_${zone_name}
-		fw add i f ${chain} input_${zone_name} ^
+		fw add $mode f input_${zone_name}
+		fw add $mode f ${chain} input_${zone_name} ^
 
-		fw add i f forwarding_${zone_name}
-		fw add i f ${chain}_forward forwarding_${zone_name} ^
+		fw add $mode f forwarding_${zone_name}
+		fw add $mode f ${chain}_forward forwarding_${zone_name} ^
 
-		fw add i n prerouting_${zone_name}
-		fw add i n ${chain}_prerouting prerouting_${zone_name} ^
+		fw add $mode n prerouting_${zone_name}
+		fw add $mode n ${chain}_prerouting prerouting_${zone_name} ^
 	}
 
 	fw_callback post zone
diff --git a/package/firewall/files/lib/core_interface.sh b/package/firewall/files/lib/core_interface.sh
index 9b35c8b2bc..de5fd9a0ea 100644
--- a/package/firewall/files/lib/core_interface.sh
+++ b/package/firewall/files/lib/core_interface.sh
@@ -17,23 +17,26 @@ fw_configure_interface() {
 
 	fw__do_rules() {
 		local action=$1
-		local chain=$2
+		local zone=$2
+		local chain=zone_${zone}
 		local ifname=$3
 
-		fw $action i f ${chain}_ACCEPT ACCEPT ^ { -o "$ifname" }
-		fw $action i f ${chain}_ACCEPT ACCEPT ^ { -i "$ifname" }
-		fw $action i f ${chain}_DROP   DROP   ^ { -o "$ifname" }
-		fw $action i f ${chain}_DROP   DROP   ^ { -i "$ifname" }
-		fw $action i f ${chain}_REJECT reject ^ { -o "$ifname" }
-		fw $action i f ${chain}_REJECT reject ^ { -i "$ifname" }
+		local mode=$(fw_get_family_mode x $zone i)
 
-		fw $action i n ${chain}_nat MASQUERADE ^ { -o "$ifname" }
-		fw $action i f ${chain}_MSSFIX TCPMSS  ^ { -o "$ifname" -p tcp --tcp-flags SYN,RST SYN --clamp-mss-to-pmtu }
+		fw $action $mode f ${chain}_ACCEPT ACCEPT ^ { -o "$ifname" }
+		fw $action $mode f ${chain}_ACCEPT ACCEPT ^ { -i "$ifname" }
+		fw $action $mode f ${chain}_DROP   DROP   ^ { -o "$ifname" }
+		fw $action $mode f ${chain}_DROP   DROP   ^ { -i "$ifname" }
+		fw $action $mode f ${chain}_REJECT reject ^ { -o "$ifname" }
+		fw $action $mode f ${chain}_REJECT reject ^ { -i "$ifname" }
 
-		fw $action i f input   ${chain}         $ { -i "$ifname" }
-		fw $action i f forward ${chain}_forward $ { -i "$ifname" }
-		fw $action i n PREROUTING ${chain}_prerouting ^ { -i "$ifname" }
-		fw $action i r PREROUTING ${chain}_notrack    ^ { -i "$ifname" }
+		fw $action $mode n ${chain}_nat MASQUERADE ^ { -o "$ifname" }
+		fw $action $mode f ${chain}_MSSFIX TCPMSS  ^ { -o "$ifname" -p tcp --tcp-flags SYN,RST SYN --clamp-mss-to-pmtu }
+
+		fw $action $mode f input   ${chain}         $ { -i "$ifname" }
+		fw $action $mode f forward ${chain}_forward $ { -i "$ifname" }
+		fw $action $mode n PREROUTING ${chain}_prerouting ^ { -i "$ifname" }
+		fw $action $mode r PREROUTING ${chain}_notrack    ^ { -i "$ifname" }
 	}
 
 	local old_zones old_ifname
@@ -42,7 +45,7 @@ fw_configure_interface() {
 		config_get old_ifname core "${iface}_ifname"
 		for z in $old_zones; do
 			fw_log info "removing $iface ($old_ifname) from zone $z"
-			fw__do_rules del zone_$z $old_ifname
+			fw__do_rules del $z $old_ifname
 
 			ACTION=remove ZONE="$z" INTERFACE="$iface" DEVICE="$ifname" /sbin/hotplug-call firewall
 		done
@@ -57,7 +60,7 @@ fw_configure_interface() {
 		list_contains zone_network "$iface" || return
 
 		fw_log info "adding $iface ($ifname) to zone $zone_name"
-		fw__do_rules add zone_${zone_name} "$ifname"
+		fw__do_rules add ${zone_name} "$ifname"
 		append new_zones $zone_name
 
 		ACTION=add ZONE="$zone_name" INTERFACE="$iface" DEVICE="$ifname" /sbin/hotplug-call firewall
diff --git a/package/firewall/files/lib/core_redirect.sh b/package/firewall/files/lib/core_redirect.sh
index 0f0ccffe00..c19c494084 100644
--- a/package/firewall/files/lib/core_redirect.sh
+++ b/package/firewall/files/lib/core_redirect.sh
@@ -16,6 +16,7 @@ fw_config_get_redirect() {
 		string dest_mac "" \
 		string dest_port "" \
 		string proto "tcpudp" \
+		string family "" \
 	} || return
 	[ -n "$redirect_name" ] || redirect_name=$redirect__name
 }
@@ -29,6 +30,8 @@ fw_load_redirect() {
 		fw_die "redirect ${redirect_name}: needs src and dest_ip"
 	}
 
+	local mode=$(fw_get_family_mode ${redirect_family:-x} $redirect_src I)
+
 	local nat_dest_port=$redirect_dest_port
 	redirect_dest_port=$(fw_get_port_range $redirect_dest_port)
 	redirect_src_port=$(fw_get_port_range $redirect_src_port)
@@ -37,7 +40,7 @@ fw_load_redirect() {
 
 	[ "$redirect_proto" == "tcpudp" ] && redirect_proto="tcp udp"
 	for redirect_proto in $redirect_proto; do
-		fw add I n zone_${redirect_src}_prerouting DNAT $ { $redirect_src_ip $redirect_dest_ip } { \
+		fw add $mode n zone_${redirect_src}_prerouting DNAT $ { $redirect_src_ip $redirect_dest_ip } { \
 			${redirect_proto:+-p $redirect_proto} \
 			${redirect_src_ip:+-s $redirect_src_ip} \
 			${redirect_src_dip:+-d $redirect_src_dip} \
@@ -47,7 +50,7 @@ fw_load_redirect() {
 			--to-destination ${redirect_dest_ip}${redirect_dest_port:+:$nat_dest_port} \
 		}
 
-		fw add I f zone_${redirect_src}_forward ACCEPT ^ { $redirect_src_ip $redirect_dest_ip } { \
+		fw add $mode f zone_${redirect_src}_forward ACCEPT ^ { $redirect_src_ip $redirect_dest_ip } { \
 			-d $redirect_dest_ip \
 			${redirect_proto:+-p $redirect_proto} \
 			${redirect_src_ip:+-s $redirect_src_ip} \
diff --git a/package/firewall/files/lib/core_rule.sh b/package/firewall/files/lib/core_rule.sh
index e6a276e5f3..1dc3f1cde6 100644
--- a/package/firewall/files/lib/core_rule.sh
+++ b/package/firewall/files/lib/core_rule.sh
@@ -16,6 +16,7 @@ fw_config_get_rule() {
 		string icmp_type "" \
 		string proto "tcpudp" \
 		string target "" \
+		string family "" \
 	} || return
 	[ -n "$rule_name" ] || rule_name=$rule__name
 	[ "$rule_proto" == "icmp" ] || rule_icmp_type=
@@ -49,9 +50,11 @@ fw_load_rule() {
 	local rule_pos
 	eval 'rule_pos=$((++FW__RULE_COUNT_'$chain'))'
 
+	local mode=$(fw_get_family_mode ${rule_family:-x} $rule_src I)
+
 	[ "$rule_proto" == "tcpudp" ] && rule_proto="tcp udp"
 	for rule_proto in $rule_proto; do
-		fw add I f $chain $target $rule_pos { $rule_src_ip $rule_dest_ip } { \
+		fw add $mode f $chain $target $rule_pos { $rule_src_ip $rule_dest_ip } { \
 			${rule_proto:+-p $rule_proto} \
 			${rule_src_ip:+-s $rule_src_ip} \
 			${rule_src_port:+--sport $rule_src_port} \
diff --git a/package/firewall/files/lib/fw.sh b/package/firewall/files/lib/fw.sh
index 1dd5227c16..553642070c 100644
--- a/package/firewall/files/lib/fw.sh
+++ b/package/firewall/files/lib/fw.sh
@@ -155,7 +155,14 @@ fw__exec() { # <action> <family> <table> <chain> <target> <position> { <rules> }
 		fi
 	fi
 	while [ $# -gt 1 ]; do
-		echo -n  "$1"
+		case "$app:$1" in
+			ip6tables:--icmp-type) echo -n "--icmpv6-type" ;;
+			ip6tables:icmp|ip6tables:ICMP) echo -n "icmpv6" ;;
+			iptables:--icmpv6-type) echo -n "--icmp-type" ;;
+			iptables:icmpv6) echo -n "icmp" ;;
+			*:}|*:{) shift; continue ;;
+			*) echo -n "$1" ;;
+		esac
 		echo -ne "\0"
 		shift
 	done | xargs -0 ${FW_TRACE:+-t} \
@@ -180,3 +187,24 @@ fw_get_port_range() {
 	fi
 }
 
+fw_get_family_mode() {
+	local hint="$1"
+	local zone="$2"
+	local mode="$3"
+
+	local ipv4 ipv6
+	[ -n "$FW_ZONES4$FW_ZONES6" ] && {
+		list_contains FW_ZONES4 $zone && ipv4=1 || ipv4=0
+		list_contains FW_ZONES6 $zone && ipv6=1 || ipv6=0
+	} || {
+		ipv4=$(uci_get_state firewall core ${zone}_ipv4 0)
+		ipv6=$(uci_get_state firewall core ${zone}_ipv6 0)
+	}
+
+	case "$hint:$ipv4:$ipv6" in
+		*4:1:*|*:1:0) echo 4 ;;
+		*6:*:1|*:0:1) echo 6 ;;
+		*) echo $mode ;;
+	esac
+}
+