X-Git-Url: https://git.rohieb.name/openwrt.git/blobdiff_plain/1efeaa35d1f86cc6e962180db9e90fc7f1698061..15a81dae2ac4c0b4af17937969eb8799cceeddb2:/package/firewall/files/lib/fw.sh diff --git a/package/firewall/files/lib/fw.sh b/package/firewall/files/lib/fw.sh index 16a39b6a6..0814ffc31 100644 --- a/package/firewall/files/lib/fw.sh +++ b/package/firewall/files/lib/fw.sh @@ -74,21 +74,8 @@ fw__exec() { # { } fw__rc $(($? & 1)) return fi - local mod - eval "mod=\$FW_${fam#G}_${tab}" - if [ "$mod" ]; then - fw__rc $mod - return - fi - case "$fam" in - *4) mod=iptable_${tab} ;; - *6) mod=ip6table_${tab} ;; - *) mod=. ;; - esac - grep -q "^${mod} " /proc/modules - mod=$? - export FW_${fam}_${tab}=$mod - fw__rc $mod + [ "$app" != ip6tables ] || [ "$tab" != nat ] + fw__rc $? } fw__err() { @@ -137,10 +124,13 @@ fw__exec() { #
{ } case "$tgt" in -) tgt= ;; esac + + local rule_offset case "$pos" in ^) pos=1 ;; $) pos= ;; -) pos= ;; + +) eval "rule_offset=\${FW__RULE_OFS_${app}_${tab}_${chn}:-1}" ;; esac if ! fw__has - family || ! fw__has $tab ; then @@ -159,13 +149,29 @@ fw__exec() { #
{ } fi fi - local cmdline="$app --table ${tab} --${cmd} ${chn} ${pol} ${pos} ${tgt:+--jump "$tgt"}" + local cmdline="$app --table ${tab} --${cmd} ${chn} ${pol} ${rule_offset:-${pos}} ${tgt:+--jump "$tgt"}" while [ $# -gt 1 ]; do - case "$app:$1" in - ip6tables:--icmp-type) cmdline="$cmdline --icmpv6-type" ;; - ip6tables:icmp|ip6tables:ICMP) cmdline="$cmdline icmpv6" ;; - iptables:--icmpv6-type) cmdline="$cmdline --icmp-type" ;; - iptables:icmpv6) cmdline="$cmdline icmp" ;; + # special parameter handling + case "$1:$2" in + -p:icmp*|-p:1|-p:58|--protocol:icmp*|--protocol:1|--protocol:58) + [ "$app" = ip6tables ] && \ + cmdline="$cmdline -p icmpv6" || \ + cmdline="$cmdline -p icmp" + shift + ;; + --icmp-type:*|--icmpv6-type:*) + local icmp_type + if [ "$app" = ip6tables ] && fw_check_icmptype6 icmp_type "$2"; then + cmdline="$cmdline $icmp_type" + elif [ "$app" = iptables ] && fw_check_icmptype4 icmp_type "$2"; then + cmdline="$cmdline $icmp_type" + else + local fam=IPv4; [ "$app" = ip6tables ] && fam=IPv6 + fw_log info "ICMP type '$2' is not valid for $fam address family, skipping rule" + return 1 + fi + shift + ;; *) cmdline="$cmdline $1" ;; esac shift @@ -175,7 +181,10 @@ fw__exec() { #
{ } $cmdline - fw__rc $? + local rv=$? + [ $rv -eq 0 ] && [ -n "$rule_offset" ] && \ + export -- "FW__RULE_OFS_${app}_${tab}_${chn}=$(($rule_offset + 1))" + fw__rc $rv } fw_get_port_range() { @@ -189,8 +198,8 @@ fw_get_port_range() { local _first=${_ports%-*} local _last=${_ports#*-} - if [ "$_first" != "$_last" ]; then - export -- "$_var=$_first$_delim$_last" + if [ "${_first#!}" != "${_last#!}" ]; then + export -- "$_var=$_first$_delim${_last#!}" else export -- "$_var=$_first" fi @@ -203,12 +212,17 @@ fw_get_family_mode() { local _mode="$4" 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 + [ "$_zone" != "*" ] && { + [ -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) + } } || { - _ipv4=$(uci_get_state firewall core ${_zone}_ipv4 0) - _ipv6=$(uci_get_state firewall core ${_zone}_ipv6 0) + _ipv4=1 + _ipv6=1 } case "$_hint:$_ipv4:$_ipv6" in @@ -221,9 +235,93 @@ fw_get_family_mode() { fw_get_negation() { local _var="$1" local _flag="$2" - local _ipaddr="$3" + local _value="$3" + + [ "${_value#!}" != "$_value" ] && \ + export -n -- "$_var=! $_flag ${_value#!}" || \ + export -n -- "$_var=${_value:+$_flag $_value}" +} + +fw_get_subnet4() { + local _var="$1" + local _flag="$2" + local _name="$3" + + local _ipaddr="$(uci_get_state network "${_name#!}" ipaddr)" + local _netmask="$(uci_get_state network "${_name#!}" netmask)" + + case "$_ipaddr" in + *.*.*.*) + [ "${_name#!}" != "$_name" ] && \ + export -n -- "$_var=! $_flag $_ipaddr/${_netmask:-255.255.255.255}" || \ + export -n -- "$_var=$_flag $_ipaddr/${_netmask:-255.255.255.255}" + return 0 + ;; + esac + + export -n -- "$_var=" + return 1 +} + +fw_check_icmptype4() { + local _var="$1" + local _type="$2" + case "$_type" in + ![0-9]*) export -n -- "$_var=! --icmp-type ${_type#!}"; return 0 ;; + [0-9]*) export -n -- "$_var=--icmp-type $_type"; return 0 ;; + esac + + [ -z "$FW_ICMP4_TYPES" ] && \ + export FW_ICMP4_TYPES=$( + iptables -p icmp -h 2>/dev/null | \ + sed -n -e '/^Valid ICMP Types:/ { + n; :r; + /router-advertisement/d; + /router-solicitation/d; + s/[()]/ /g; s/[[:space:]]\+/\n/g; p; n; b r + }' | sort -u + ) + + local _check + for _check in $FW_ICMP4_TYPES; do + if [ "$_check" = "${_type#!}" ]; then + [ "${_type#!}" != "$_type" ] && \ + export -n -- "$_var=! --icmp-type ${_type#!}" || \ + export -n -- "$_var=--icmp-type $_type" + return 0 + fi + done + + export -n -- "$_var=" + return 1 +} + +fw_check_icmptype6() { + local _var="$1" + local _type="$2" + case "$_type" in + ![0-9]*) export -n -- "$_var=! --icmpv6-type ${_type#!}"; return 0 ;; + [0-9]*) export -n -- "$_var=--icmpv6-type $_type"; return 0 ;; + esac + + [ -z "$FW_ICMP6_TYPES" ] && \ + export FW_ICMP6_TYPES=$( + ip6tables -p icmpv6 -h 2>/dev/null | \ + sed -n -e '/^Valid ICMPv6 Types:/ { + n; :r; s/[()]/ /g; s/[[:space:]]\+/\n/g; p; n; b r + }' | sort -u + ) + + local _check + for _check in $FW_ICMP6_TYPES; do + if [ "$_check" = "${_type#!}" ]; then + [ "${_type#!}" != "$_type" ] && \ + export -n -- "$_var=! --icmpv6-type ${_type#!}" || \ + export -n -- "$_var=--icmpv6-type $_type" + return 0 + fi + done - [ "${_ipaddr#!}" != "$_ipaddr" ] && \ - export -n -- "$_var=! $_flag ${_ipaddr#!}" || \ - export -n -- "$_var=${_ipaddr:+$_flag $_ipaddr}" + export -n -- "$_var=" + return 1 }