firewall: - fix ip6tables rules when icmp_type option is set - add "family" option...
authorJo-Philipp Wich <jow@openwrt.org>
Wed, 19 May 2010 21:35:23 +0000 (21:35 +0000)
committerJo-Philipp Wich <jow@openwrt.org>
Wed, 19 May 2010 21:35:23 +0000 (21:35 +0000)
SVN-Revision: 21508

package/firewall/Makefile
package/firewall/files/lib/core_forwarding.sh
package/firewall/files/lib/core_init.sh
package/firewall/files/lib/core_interface.sh
package/firewall/files/lib/core_redirect.sh
package/firewall/files/lib/core_rule.sh
package/firewall/files/lib/fw.sh

index 1a7216ce175ce9efc15e9aa054d4b8970dfe4796..4f4f71c325c0adcb27d97d91051f8c79e40c6202 100644 (file)
@@ -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
 
index 766e48e38ec95df11cc4e2e01e3ba5bc72088e2c..689e2628c23968745815d93125b5226aaa418780 100644 (file)
@@ -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 && {
index 2dd989e4948673b6e725d4e4e1a6faf7685ae36c..92d117160f6291ba9c0bdf977f2eb80072d38ea1 100644 (file)
@@ -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
index 9b35c8b2bcc61b01fe22003ae611a44936d8c820..de5fd9a0ea38a54be82c9de767236b832feeb2f6 100644 (file)
@@ -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
index 0f0ccffe0000bbb443f7cb08a50345ff05300a41..c19c494084e8399dc3d851b31d3df67d6eb16633 100644 (file)
@@ -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} \
index e6a276e5f3a31716c4af69e468d8e5e29bc19fe5..1dc3f1cde6ff756997f924058db4a7111adae9ae 100644 (file)
@@ -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} \
index 1dd5227c164f6147f03b8e523ce283ed8ebfb01d..553642070ca34745dc9e65187cf7393bd0e115e7 100644 (file)
@@ -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
+}
+