diff --git a/mwan3/Makefile b/mwan3/Makefile index f4d03e63d..958c21061 100644 --- a/mwan3/Makefile +++ b/mwan3/Makefile @@ -8,8 +8,8 @@ include $(TOPDIR)/rules.mk PKG_NAME:=mwan3 -PKG_VERSION:=2.8.8 -PKG_RELEASE:=2 +PKG_VERSION:=2.8.12 +PKG_RELEASE:=1 PKG_MAINTAINER:=Florian Eckert PKG_LICENSE:=GPL-2.0 diff --git a/mwan3/files/etc/config/mwan3 b/mwan3/files/etc/config/mwan3 index 22c9c6d80..f88769c72 100644 --- a/mwan3/files/etc/config/mwan3 +++ b/mwan3/files/etc/config/mwan3 @@ -18,6 +18,12 @@ config rule 'https' option proto 'tcp' option use_policy 'balanced' -config rule 'default_rule' +config rule 'default_rule_v4' option dest_ip '0.0.0.0/0' option use_policy 'balanced' + option family 'ipv4' + +config rule 'default_rule_v6' + option dest_ip '::/0' + option use_policy 'balanced' + option family 'ipv6' diff --git a/mwan3/files/etc/hotplug.d/iface/15-mwan3 b/mwan3/files/etc/hotplug.d/iface/15-mwan3 index 5bfbd2462..645cdd3e4 100644 --- a/mwan3/files/etc/hotplug.d/iface/15-mwan3 +++ b/mwan3/files/etc/hotplug.d/iface/15-mwan3 @@ -9,24 +9,29 @@ [ -n "$INTERFACE" ] || exit 2 if [ "$ACTION" == "ifup" ]; then - [ -n "$DEVICE" ] || exit 3 + [ -n "$DEVICE" ] || exit 3 fi +mwan3_lock "$ACTION" "$INTERFACE" config_load mwan3 config_get_bool enabled globals 'enabled' '0' -[ ${enabled} -gt 0 ] || exit 0 +[ "${enabled}" -gt 0 ] || { + mwan3_unlock "$ACTION" "$INTERFACE" + exit 0 +} -mwan3_lock "$ACTION" "$INTERFACE" mwan3_init mwan3_set_connected_iptables mwan3_set_custom_ipset -mwan3_unlock "$ACTION" "$INTERFACE" -config_get enabled $INTERFACE enabled 0 config_get initial_state $INTERFACE initial_state "online" -[ "$enabled" == "1" ] || exit 0 +config_get_bool enabled $INTERFACE 'enabled' '0' +[ "${enabled}" -eq 1 ] || { + mwan3_unlock "$ACTION" "$INTERFACE" + exit 0 +} -if [ "$ACTION" == "ifup" ]; then +if [ "$ACTION" = "ifup" ]; then config_get family $INTERFACE family ipv4 if [ "$family" = "ipv4" ]; then ubus call network.interface.${INTERFACE}_4 status &>/dev/null @@ -58,7 +63,6 @@ else running=1 fi -mwan3_lock "$ACTION" "$INTERFACE" $LOG notice "Execute "$ACTION" event on interface $INTERFACE (${DEVICE:-unknown})" case "$ACTION" in @@ -68,7 +72,7 @@ case "$ACTION" in mwan3_create_iface_iptables $INTERFACE $DEVICE mwan3_create_iface_rules $INTERFACE $DEVICE mwan3_create_iface_route $INTERFACE $DEVICE - if [ ${running} -eq 1 -a "${status}" = "online" ]; then + if [ "${running}" -eq 1 ] && [ "${status}" = "online" ]; then $LOG notice "Starting tracker on interface $INTERFACE (${DEVICE:-unknown})" mwan3_set_iface_hotplug_state $INTERFACE "online" mwan3_track $INTERFACE $DEVICE "online" "$src_ip" diff --git a/mwan3/files/etc/hotplug.d/iface/16-mwan3 b/mwan3/files/etc/hotplug.d/iface/16-mwan3 index c243d55ff..dd09358eb 100644 --- a/mwan3/files/etc/hotplug.d/iface/16-mwan3 +++ b/mwan3/files/etc/hotplug.d/iface/16-mwan3 @@ -4,19 +4,24 @@ . /lib/functions/network.sh . /lib/mwan3/mwan3.sh +mwan3_lock "$ACTION" "mwan3rtmon" + config_load mwan3 config_get_bool enabled globals 'enabled' '0' -[ ${enabled} -gt 0 ] || exit 0 - -if [ "$ACTION" == "ifup" ]; then - mwan3_lock "$ACTION" "mwan3rtmon" - mwan3_rtmon +[ "${enabled}" -gt 0 ] || { mwan3_unlock "$ACTION" "mwan3rtmon" + exit 0 +} + +if [ "$ACTION" = "ifup" ]; then + mwan3_rtmon fi -config_get enabled $INTERFACE enabled 0 -[ "${enabled}" = "0" ] || { +config_get_bool enabled "$INTERFACE" 'enabled' '0' +[ "${enabled}" -eq 0 ] || { mwan3_flush_conntrack "$INTERFACE" "$ACTION" } +mwan3_unlock "$ACTION" "mwan3rtmon" + exit 0 diff --git a/mwan3/files/etc/hotplug.d/iface/16-mwan3-user b/mwan3/files/etc/hotplug.d/iface/16-mwan3-user index 9372c736e..af28b1f4f 100644 --- a/mwan3/files/etc/hotplug.d/iface/16-mwan3-user +++ b/mwan3/files/etc/hotplug.d/iface/16-mwan3-user @@ -2,13 +2,25 @@ [ -f "/etc/mwan3.user" ] && { . /lib/functions.sh + . /lib/mwan3/mwan3.sh + + mwan3_lock "$ACTION" "user" config_load mwan3 config_get_bool enabled globals 'enabled' '0' - [ ${enabled} -gt 0 ] || exit 0 + [ "${enabled}" -gt 0 ] || { + mwan3_unlock "$ACTION" "user" + exit 0 + } + + config_get_bool enabled "$INTERFACE" enabled 0 + [ "${enabled}" -eq 1 ] || { + mwan3_unlock "$ACTION" "user" + exit 0 + } + + mwan3_unlock "$ACTION" "user" - config_get enabled "$INTERFACE" enabled 0 - [ "${enabled}" = "1" ] || exit 0 env -i ACTION="$ACTION" INTERFACE="$INTERFACE" DEVICE="$DEVICE" \ /bin/sh /etc/mwan3.user } diff --git a/mwan3/files/etc/init.d/mwan3 b/mwan3/files/etc/init.d/mwan3 index af750e55e..e0c65889a 100755 --- a/mwan3/files/etc/init.d/mwan3 +++ b/mwan3/files/etc/init.d/mwan3 @@ -10,17 +10,22 @@ boot() { rc_procd start_service } +# FIXME +# fd 1000 is an inherited lock file descriptor for preventing concurrent +# init script executions. Close it here to prevent the mwan3 daemon from +# inheriting it further to avoid holding the lock indefinitely. + reload_service() { - /usr/sbin/mwan3 restart + /usr/sbin/mwan3 restart 1000>&- } start_service() { [ -n "${mwan3_boot}" ] && return 0 - /usr/sbin/mwan3 start + /usr/sbin/mwan3 start 1000>&- } stop_service() { - /usr/sbin/mwan3 stop + /usr/sbin/mwan3 stop 1000>&- } service_triggers() { diff --git a/mwan3/files/lib/mwan3/mwan3.sh b/mwan3/files/lib/mwan3/mwan3.sh index 64b07d658..3c7422dc0 100644 --- a/mwan3/files/lib/mwan3/mwan3.sh +++ b/mwan3/files/lib/mwan3/mwan3.sh @@ -1,5 +1,7 @@ #!/bin/sh +. /usr/share/libubox/jshn.sh + IP4="ip -4" IP6="ip -6" IPS="ipset" @@ -32,21 +34,32 @@ MM_BLACKHOLE="" MMX_UNREACHABLE="" MM_UNREACHABLE="" +command -v ip6tables > /dev/null +NO_IPV6=$? + # return true(=0) if has any mwan3 interface enabled # otherwise return false mwan3_rtmon_ipv4() { - local tid=1 local idx=0 local ret=1 local tbl="" + + local tid family enabled + mkdir -p /tmp/mwan3rtmon ($IP4 route list table main | grep -v "^default\|linkdown" | sort -n; echo empty fixup) >/tmp/mwan3rtmon/ipv4.main while uci get mwan3.@interface[$idx] >/dev/null 2>&1 ; do - idx=$((idx+1)) - tid=$idx - [ "$(uci get mwan3.@interface[$((idx-1))].family)" = "ipv4" ] && { - tbl=$($IP4 route list table $tid) + tid=$((idx+1)) + + family="$(uci -q get mwan3.@interface[$idx].family)" + [ -z "$family" ] && family="ipv4" + + enabled="$(uci -q get mwan3.@interface[$idx].enabled)" + [ -z "$enabled" ] && enabled="0" + + [ "$family" = "ipv4" ] && { + tbl=$($IP4 route list table $tid 2>/dev/null) if echo "$tbl" | grep -q ^default; then (echo "$tbl" | grep -v "^default\|linkdown" | sort -n; echo empty fixup) >/tmp/mwan3rtmon/ipv4.$tid cat /tmp/mwan3rtmon/ipv4.$tid | grep -v -x -F -f /tmp/mwan3rtmon/ipv4.main | while read line; do @@ -57,9 +70,10 @@ mwan3_rtmon_ipv4() done fi } - if [ "$(uci get mwan3.@interface[$((idx-1))].enabled)" = "1" ]; then + if [ "$enabled" = "1" ]; then ret=0 fi + idx=$((idx+1)) done rm -f /tmp/mwan3rtmon/ipv4.* return $ret @@ -69,17 +83,26 @@ mwan3_rtmon_ipv4() # otherwise return false mwan3_rtmon_ipv6() { - local tid=1 local idx=0 local ret=1 local tbl="" + + local tid family enabled + mkdir -p /tmp/mwan3rtmon ($IP6 route list table main | grep -v "^default\|^::/0\|^fe80::/64\|^unreachable" | sort -n; echo empty fixup) >/tmp/mwan3rtmon/ipv6.main while uci get mwan3.@interface[$idx] >/dev/null 2>&1 ; do - idx=$((idx+1)) - tid=$idx - [ "$(uci get mwan3.@interface[$((idx-1))].family)" = "ipv6" ] && { - tbl=$($IP6 route list table $tid) + tid=$((idx+1)) + + family="$(uci -q get mwan3.@interface[$idx].family)" + # Set default family to ipv4 that is no mistake + [ -z "$family" ] && family="ipv4" + + enabled="$(uci -q get mwan3.@interface[$idx].enabled)" + [ -z "$enabled" ] && enabled="0" + + [ "$family" = "ipv6" ] && { + tbl=$($IP6 route list table $tid 2>/dev/null) if echo "$tbl" | grep -q "^default\|^::/0"; then (echo "$tbl" | grep -v "^default\|^::/0\|^unreachable" | sort -n; echo empty fixup) >/tmp/mwan3rtmon/ipv6.$tid cat /tmp/mwan3rtmon/ipv6.$tid | grep -v -x -F -f /tmp/mwan3rtmon/ipv6.main | while read line; do @@ -90,9 +113,10 @@ mwan3_rtmon_ipv6() done fi } - if [ "$(uci get mwan3.@interface[$((idx-1))].enabled)" = "1" ]; then + if [ "$enabled" = "1" ]; then ret=0 fi + idx=$((idx+1)) done rm -f /tmp/mwan3rtmon/ipv6.* return $ret @@ -179,10 +203,6 @@ mwan3_unlock() { lock -u /var/run/mwan3.lock } -mwan3_lock_clean() { - rm -rf /var/run/mwan3.lock -} - mwan3_get_iface_id() { local _tmp _iface _iface_count @@ -192,7 +212,7 @@ mwan3_get_iface_id() mwan3_get_id() { let _iface_count++ - [ "$1" == "$_iface" ] && _tmp=$_iface_count + [ "$1" = "$_iface" ] && _tmp=$_iface_count } config_foreach mwan3_get_id interface export "$1=$_tmp" @@ -204,7 +224,7 @@ mwan3_set_custom_ipset_v4() for custom_network_v4 in $($IP4 route list table "$1" | awk '{print $1}' | egrep '[0-9]{1,3}(\.[0-9]{1,3}){3}'); do $LOG notice "Adding network $custom_network_v4 from table $1 to mwan3_custom_v4 ipset" - $IPS -! add mwan3_custom_v4_temp $custom_network_v4 + $IPS -! add mwan3_custom_v4_temp "$custom_network_v4" done } @@ -214,7 +234,7 @@ mwan3_set_custom_ipset_v6() for custom_network_v6 in $($IP6 route list table "$1" | awk '{print $1}' | egrep "$IPv6_REGEX"); do $LOG notice "Adding network $custom_network_v6 from table $1 to mwan3_custom_v6 ipset" - $IPS -! add mwan3_custom_v6_temp $custom_network_v6 + $IPS -! add mwan3_custom_v6_temp "$custom_network_v6" done } @@ -238,19 +258,30 @@ mwan3_set_custom_ipset() $IPS -! add mwan3_connected mwan3_custom_v6 } -mwan3_set_connected_iptables() + +mwan3_set_connected_ipv4() { - local connected_network_v4 connected_network_v6 source_network_v6 - - $IPS -! create mwan3_connected_v4 hash:net - $IPS create mwan3_connected_v4_temp hash:net - + local connected_network_v4 candidate_list cidr_list + candidate_list="" + cidr_list="" for connected_network_v4 in $($IP4 route | awk '{print $1}' | egrep '[0-9]{1,3}(\.[0-9]{1,3}){3}'); do - $IPS -! add mwan3_connected_v4_temp $connected_network_v4 + [ -z "${connected_network_v4##*/*}" ] && + cidr_list="$cidr_list $connected_network_v4" || + candidate_list="$candidate_list $connected_network_v4" done for connected_network_v4 in $($IP4 route list table 0 | awk '{print $2}' | egrep '[0-9]{1,3}(\.[0-9]{1,3}){3}'); do - $IPS -! add mwan3_connected_v4_temp $connected_network_v4 + [ -z "${connected_network_v4##*/*}" ] && + cidr_list="$cidr_list $connected_network_v4" || + candidate_list="$candidate_list $connected_network_v4" + done + + for connected_network_v4 in $cidr_list; do + $IPS -! add mwan3_connected_v4_temp "$connected_network_v4" + done + for connected_network_v4 in $candidate_list; do + ipset -q test mwan3_connected_v4_temp "$connected_network_v4" || + $IPS -! add mwan3_connected_v4_temp "$connected_network_v4" done $IPS add mwan3_connected_v4_temp 224.0.0.0/3 @@ -258,33 +289,45 @@ mwan3_set_connected_iptables() $IPS swap mwan3_connected_v4_temp mwan3_connected_v4 $IPS destroy mwan3_connected_v4_temp - $IPS -! create mwan3_connected_v6 hash:net family inet6 - $IPS create mwan3_connected_v6_temp hash:net family inet6 +} - for connected_network_v6 in $($IP6 route | awk '{print $1}' | egrep "$IPv6_REGEX"); do - $IPS -! add mwan3_connected_v6_temp $connected_network_v6 - done +mwan3_set_connected_iptables() +{ + local connected_network_v6 source_network_v6 - $IPS swap mwan3_connected_v6_temp mwan3_connected_v6 - $IPS destroy mwan3_connected_v6_temp + $IPS -! create mwan3_connected_v4 hash:net + $IPS create mwan3_connected_v4_temp hash:net + + mwan3_set_connected_ipv4 + + [ $NO_IPV6 -eq 0 ] && { + $IPS -! create mwan3_connected_v6 hash:net family inet6 + $IPS create mwan3_connected_v6_temp hash:net family inet6 + + for connected_network_v6 in $($IP6 route | awk '{print $1}' | egrep "$IPv6_REGEX"); do + $IPS -! add mwan3_connected_v6_temp "$connected_network_v6" + done + $IPS swap mwan3_connected_v6_temp mwan3_connected_v6 + $IPS destroy mwan3_connected_v6_temp + + $IPS -! create mwan3_source_v6 hash:net family inet6 + $IPS create mwan3_source_v6_temp hash:net family inet6 + for source_network_v6 in $($IP6 addr ls | sed -ne 's/ *inet6 \([^ \/]*\).* scope global.*/\1/p'); do + $IPS -! add mwan3_source_v6_temp "$source_network_v6" + done + $IPS swap mwan3_source_v6_temp mwan3_source_v6 + $IPS destroy mwan3_source_v6_temp + } $IPS -! create mwan3_connected list:set $IPS -! add mwan3_connected mwan3_connected_v4 - $IPS -! add mwan3_connected mwan3_connected_v6 - - $IPS -! create mwan3_source_v6 hash:net family inet6 - $IPS create mwan3_source_v6_temp hash:net family inet6 - for source_network_v6 in $($IP6 addr ls | sed -ne 's/ *inet6 \([^ \/]*\).* scope global.*/\1/p'); do - $IPS -! add mwan3_source_v6_temp $source_network_v6 - done - $IPS swap mwan3_source_v6_temp mwan3_source_v6 - $IPS destroy mwan3_source_v6_temp + [ $NO_IPV6 -eq 0 ] && $IPS -! add mwan3_connected mwan3_connected_v6 $IPS -! create mwan3_dynamic_v4 hash:net $IPS -! add mwan3_connected mwan3_dynamic_v4 - $IPS -! create mwan3_dynamic_v6 hash:net family inet6 - $IPS -! add mwan3_connected mwan3_dynamic_v6 + [ $NO_IPV6 -eq 0 ] && $IPS -! create mwan3_dynamic_v6 hash:net family inet6 + [ $NO_IPV6 -eq 0 ] && $IPS -! add mwan3_connected mwan3_dynamic_v6 } mwan3_set_general_rules() @@ -292,7 +335,7 @@ mwan3_set_general_rules() local IP for IP in "$IP4" "$IP6"; do - + [ "$IP" = "$IP6" ] && [ $NO_IPV6 -ne 0 ] && continue RULE_NO=$(($MM_BLACKHOLE+2000)) if [ -z "$($IP rule list | awk -v var="$RULE_NO:" '$1 == var')" ]; then $IP rule add pref $RULE_NO fwmark $MMX_BLACKHOLE/$MMX_MASK blackhole @@ -310,7 +353,7 @@ mwan3_set_general_iptables() local IPT for IPT in "$IPT4" "$IPT6"; do - + [ "$IPT" = "$IPT6" ] && [ $NO_IPV6 -ne 0 ] && continue if ! $IPT -S mwan3_ifaces_in &> /dev/null; then $IPT -N mwan3_ifaces_in fi @@ -360,7 +403,7 @@ mwan3_set_general_iptables() fi $IPT -A mwan3_hook \ - -j CONNMARK --restore-mark --nfmask $MMX_MASK --ctmask $MMX_MASK + -j CONNMARK --restore-mark --nfmask "$MMX_MASK" --ctmask "$MMX_MASK" $IPT -A mwan3_hook \ -m mark --mark 0x0/$MMX_MASK \ -j mwan3_ifaces_in @@ -371,7 +414,7 @@ mwan3_set_general_iptables() -m mark --mark 0x0/$MMX_MASK \ -j mwan3_rules $IPT -A mwan3_hook \ - -j CONNMARK --save-mark --nfmask $MMX_MASK --ctmask $MMX_MASK + -j CONNMARK --save-mark --nfmask "$MMX_MASK" --ctmask "$MMX_MASK" $IPT -A mwan3_hook \ -m mark ! --mark $MMX_DEFAULT/$MMX_MASK \ -j mwan3_connected @@ -389,169 +432,133 @@ mwan3_set_general_iptables() mwan3_create_iface_iptables() { - local id family + local id family connected_name IPT - config_get family $1 family ipv4 - mwan3_get_iface_id id $1 + config_get family "$1" family ipv4 + mwan3_get_iface_id id "$1" [ -n "$id" ] || return 0 - if [ "$family" == "ipv4" ]; then - $IPS -! create mwan3_connected list:set + if [ "$family" = "ipv4" ]; then + connected_name=mwan3_connected + IPT="$IPT4" + $IPS -! create $connected_name list:set - if ! $IPT4 -S mwan3_ifaces_in &> /dev/null; then - $IPT4 -N mwan3_ifaces_in - fi - - if ! $IPT4 -S mwan3_iface_in_$1 &> /dev/null; then - $IPT4 -N mwan3_iface_in_$1 - fi - - $IPT4 -F mwan3_iface_in_$1 - $IPT4 -A mwan3_iface_in_$1 \ - -i $2 \ - -m set --match-set mwan3_connected src \ - -m mark --mark 0x0/$MMX_MASK \ - -m comment --comment "default" \ - -j MARK --set-xmark $MMX_DEFAULT/$MMX_MASK - $IPT4 -A mwan3_iface_in_$1 \ - -i $2 \ - -m mark --mark 0x0/$MMX_MASK \ - -m comment --comment "$1" \ - -j MARK --set-xmark $(mwan3_id2mask id MMX_MASK)/$MMX_MASK - - $IPT4 -D mwan3_ifaces_in \ - -m mark --mark 0x0/$MMX_MASK \ - -j mwan3_iface_in_$1 &> /dev/null - $IPT4 -A mwan3_ifaces_in \ - -m mark --mark 0x0/$MMX_MASK \ - -j mwan3_iface_in_$1 + elif [ "$family" = "ipv6" ] && [ $NO_IPV6 -eq 0 ]; then + connected_name=mwan3_connected_v6 + IPT="$IPT6" + $IPS -! create $connected_name hash:net family inet6 + else + return fi - if [ "$family" == "ipv6" ]; then - $IPS -! create mwan3_connected_v6 hash:net family inet6 - - if ! $IPT6 -S mwan3_ifaces_in &> /dev/null; then - $IPT6 -N mwan3_ifaces_in - fi - - if ! $IPT6 -S mwan3_iface_in_$1 &> /dev/null; then - $IPT6 -N mwan3_iface_in_$1 - fi - - $IPT6 -F mwan3_iface_in_$1 - $IPT6 -A mwan3_iface_in_$1 -i $2 \ - -m set --match-set mwan3_connected_v6 src \ - -m mark --mark 0x0/$MMX_MASK \ - -m comment --comment "default" \ - -j MARK --set-xmark $MMX_DEFAULT/$MMX_MASK - $IPT6 -A mwan3_iface_in_$1 -i $2 -m mark --mark 0x0/$MMX_MASK \ - -m comment --comment "$1" \ - -j MARK --set-xmark $(mwan3_id2mask id MMX_MASK)/$MMX_MASK - - $IPT6 -D mwan3_ifaces_in \ - -m mark --mark 0x0/$MMX_MASK \ - -j mwan3_iface_in_$1 &> /dev/null - $IPT6 -A mwan3_ifaces_in \ - -m mark --mark 0x0/$MMX_MASK \ - -j mwan3_iface_in_$1 + if ! $IPT -S mwan3_ifaces_in &> /dev/null; then + $IPT -N mwan3_ifaces_in fi + + if ! $IPT -S "mwan3_iface_in_$1" &> /dev/null; then + $IPT -N "mwan3_iface_in_$1" + fi + + $IPT -F "mwan3_iface_in_$1" + $IPT -A "mwan3_iface_in_$1" \ + -i "$2" \ + -m set --match-set $connected_name src \ + -m mark --mark 0x0/$MMX_MASK \ + -m comment --comment "default" \ + -j MARK --set-xmark $MMX_DEFAULT/$MMX_MASK + $IPT -A "mwan3_iface_in_$1" \ + -i "$2" \ + -m mark --mark 0x0/$MMX_MASK \ + -m comment --comment "$1" \ + -j MARK --set-xmark $(mwan3_id2mask id MMX_MASK)/$MMX_MASK + + $IPT -D mwan3_ifaces_in \ + -m mark --mark 0x0/$MMX_MASK \ + -j "mwan3_iface_in_$1" &> /dev/null + $IPT -A mwan3_ifaces_in \ + -m mark --mark 0x0/$MMX_MASK \ + -j "mwan3_iface_in_$1" + } mwan3_delete_iface_iptables() { - config_get family $1 family ipv4 + local IPT + config_get family "$1" family ipv4 - if [ "$family" == "ipv4" ]; then - - $IPT4 -D mwan3_ifaces_in \ - -m mark --mark 0x0/$MMX_MASK \ - -j mwan3_iface_in_$1 &> /dev/null - $IPT4 -F mwan3_iface_in_$1 &> /dev/null - $IPT4 -X mwan3_iface_in_$1 &> /dev/null + if [ "$family" = "ipv4" ]; then + IPT="$IPT4" fi - if [ "$family" == "ipv6" ]; then - - $IPT6 -D mwan3_ifaces_in \ - -m mark --mark 0x0/$MMX_MASK \ - -j mwan3_iface_in_$1 &> /dev/null - $IPT6 -F mwan3_iface_in_$1 &> /dev/null - $IPT6 -X mwan3_iface_in_$1 &> /dev/null + if [ "$family" = "ipv6" ]; then + [ $NO_IPV6 -ne 0 ] && return + IPT="$IPT6" fi + + $IPT -D mwan3_ifaces_in \ + -m mark --mark 0x0/$MMX_MASK \ + -j "mwan3_iface_in_$1" &> /dev/null + $IPT -F "mwan3_iface_in_$1" &> /dev/null + $IPT -X "mwan3_iface_in_$1" &> /dev/null + } mwan3_create_iface_route() { - local id route_args metric + local id via metric V V_ IP - config_get family $1 family ipv4 - mwan3_get_iface_id id $1 + config_get family "$1" family ipv4 + mwan3_get_iface_id id "$1" [ -n "$id" ] || return 0 - if [ "$family" == "ipv4" ]; then - if ubus call network.interface.${1}_4 status &>/dev/null; then - network_get_gateway route_args ${1}_4 - else - network_get_gateway route_args $1 - fi - - if [ -n "$route_args" -a "$route_args" != "0.0.0.0" ]; then - route_args="via $route_args" - else - route_args="" - fi - - network_get_metric metric $1 - if [ -n "$metric" -a "$metric" != "0" ]; then - route_args="$route_args metric $metric" - fi - - $IP4 route flush table $id - $IP4 route add table $id default $route_args dev $2 - mwan3_rtmon_ipv4 + if [ "$family" = "ipv4" ]; then + V=4 + V_="" + IP="$IP4" + elif [ "$family" = "ipv6" ]; then + V=6 + V_=6 + IP="$IP6" + else + return fi - if [ "$family" == "ipv6" ]; then - if ubus call network.interface.${1}_6 status &>/dev/null; then - network_get_gateway6 route_args ${1}_6 - else - network_get_gateway6 route_args $1 - fi - - if [ -n "$route_args" -a "$route_args" != "::" ]; then - route_args="via $route_args" - else - route_args="" - fi - - network_get_metric metric $1 - if [ -n "$metric" -a "$metric" != "0" ]; then - route_args="$route_args metric $metric" - fi - - $IP6 route flush table $id - $IP6 route add table $id default $route_args dev $2 - mwan3_rtmon_ipv6 + if ubus call network.interface.${1}_${V} status &>/dev/null; then + network_get_gateway${V_} via "${1}_${V}" + else + network_get_gateway${V_} via "$1" fi + + ( [ -z "$via" ] || [ "$via" = "0.0.0.0" ] || [ "$via" = "::" ] ) && unset via + + network_get_metric metric "$1" + + $IP route flush table "$id" + $IP route add table "$id" default \ + ${via:+via} $via \ + ${metric:+metric} $metric \ + dev "$2" + mwan3_rtmon_ipv${V} + } mwan3_delete_iface_route() { local id - config_get family $1 family ipv4 - mwan3_get_iface_id id $1 + config_get family "$1" family ipv4 + mwan3_get_iface_id id "$1" [ -n "$id" ] || return 0 - if [ "$family" == "ipv4" ]; then - $IP4 route flush table $id + if [ "$family" = "ipv4" ]; then + $IP4 route flush table "$id" fi - if [ "$family" == "ipv6" ]; then - $IP6 route flush table $id + if [ "$family" = "ipv6" ] && [ $NO_IPV6 -eq 0 ]; then + $IP6 route flush table "$id" fi } @@ -559,12 +566,12 @@ mwan3_create_iface_rules() { local id family - config_get family $1 family ipv4 - mwan3_get_iface_id id $1 + config_get family "$1" family ipv4 + mwan3_get_iface_id id "$1" [ -n "$id" ] || return 0 - if [ "$family" == "ipv4" ]; then + if [ "$family" = "ipv4" ]; then while [ -n "$($IP4 rule list | awk '$1 == "'$(($id+1000)):'"')" ]; do $IP4 rule del pref $(($id+1000)) @@ -574,11 +581,11 @@ mwan3_create_iface_rules() $IP4 rule del pref $(($id+2000)) done - $IP4 rule add pref $(($id+1000)) iif $2 lookup $id - $IP4 rule add pref $(($id+2000)) fwmark $(mwan3_id2mask id MMX_MASK)/$MMX_MASK lookup $id + $IP4 rule add pref $(($id+1000)) iif "$2" lookup "$id" + $IP4 rule add pref $(($id+2000)) fwmark $(mwan3_id2mask id MMX_MASK)/$MMX_MASK lookup "$id" fi - if [ "$family" == "ipv6" ]; then + if [ "$family" = "ipv6" ] && [ $NO_IPV6 -eq 0 ]; then while [ -n "$($IP6 rule list | awk '$1 == "'$(($id+1000)):'"')" ]; do $IP6 rule del pref $(($id+1000)) @@ -588,8 +595,8 @@ mwan3_create_iface_rules() $IP6 rule del pref $(($id+2000)) done - $IP6 rule add pref $(($id+1000)) iif $2 lookup $id - $IP6 rule add pref $(($id+2000)) fwmark $(mwan3_id2mask id MMX_MASK)/$MMX_MASK lookup $id + $IP6 rule add pref $(($id+1000)) iif "$2" lookup "$id" + $IP6 rule add pref $(($id+2000)) fwmark $(mwan3_id2mask id MMX_MASK)/$MMX_MASK lookup "$id" fi } @@ -597,12 +604,12 @@ mwan3_delete_iface_rules() { local id family - config_get family $1 family ipv4 - mwan3_get_iface_id id $1 + config_get family "$1" family ipv4 + mwan3_get_iface_id id "$1" [ -n "$id" ] || return 0 - if [ "$family" == "ipv4" ]; then + if [ "$family" = "ipv4" ]; then while [ -n "$($IP4 rule list | awk '$1 == "'$(($id+1000)):'"')" ]; do $IP4 rule del pref $(($id+1000)) @@ -613,7 +620,7 @@ mwan3_delete_iface_rules() done fi - if [ "$family" == "ipv6" ]; then + if [ "$family" = "ipv6" ] && [ $NO_IPV6 -eq 0 ]; then while [ -n "$($IP6 rule list | awk '$1 == "'$(($id+1000)):'"')" ]; do $IP6 rule del pref $(($id+1000)) @@ -629,13 +636,13 @@ mwan3_delete_iface_ipset_entries() { local id setname entry - mwan3_get_iface_id id $1 + mwan3_get_iface_id id "$1" [ -n "$id" ] || return 0 for setname in $(ipset -n list | grep ^mwan3_sticky_); do - for entry in $(ipset list $setname | grep "$(echo $(mwan3_id2mask id MMX_MASK) | awk '{ printf "0x%08x", $1; }')" | cut -d ' ' -f 1); do - $IPS del $setname $entry + for entry in $(ipset list "$setname" | grep "$(echo $(mwan3_id2mask id MMX_MASK) | awk '{ printf "0x%08x", $1; }')" | cut -d ' ' -f 1); do + $IPS del "$setname" $entry done done } @@ -658,11 +665,13 @@ mwan3_track() { track_ips="$track_ips $1" } - config_list_foreach $1 track_ip mwan3_list_track_ips + config_list_foreach "$1" track_ip mwan3_list_track_ips for pid in $(pgrep -f "mwan3track $1 $2"); do kill -TERM "$pid" > /dev/null 2>&1 - sleep 1 + done + sleep 1 + for pid in $(pgrep -f "mwan3track $1 $2"); do kill -KILL "$pid" > /dev/null 2>&1 done if [ -n "$track_ips" ]; then @@ -682,117 +691,87 @@ mwan3_track_signal() mwan3_set_policy() { - local iface_count id iface family metric probability weight device + local iface_count id iface family metric probability weight device is_lowest is_offline IPT total_weight - config_get iface $1 interface - config_get metric $1 metric 1 - config_get weight $1 weight 1 + is_lowest=0 + config_get iface "$1" interface + config_get metric "$1" metric 1 + config_get weight "$1" weight 1 [ -n "$iface" ] || return 0 - network_get_device device $iface + network_get_device device "$iface" [ "$metric" -gt $DEFAULT_LOWEST_METRIC ] && $LOG warn "Member interface $iface has >$DEFAULT_LOWEST_METRIC metric. Not appending to policy" && return 0 - mwan3_get_iface_id id $iface + mwan3_get_iface_id id "$iface" + + [ "$(mwan3_get_iface_hotplug_state "$iface")" = "online" ] + is_offline=$? [ -n "$id" ] || return 0 - config_get family $iface family ipv4 + config_get family "$iface" family ipv4 - if [ "$family" == "ipv4" ]; then - - if [ "$(mwan3_get_iface_hotplug_state $iface)" = "online" ]; then - if [ "$metric" -lt "$lowest_metric_v4" ]; then - - total_weight_v4=$weight - $IPT4 -F mwan3_policy_$policy - $IPT4 -A mwan3_policy_$policy \ - -m mark --mark 0x0/$MMX_MASK \ - -m comment --comment "$iface $weight $weight" \ - -j MARK --set-xmark $(mwan3_id2mask id MMX_MASK)/$MMX_MASK - - lowest_metric_v4=$metric - - elif [ "$metric" -eq "$lowest_metric_v4" ]; then - - total_weight_v4=$(($total_weight_v4+$weight)) - probability=$(($weight*1000/$total_weight_v4)) - - if [ "$probability" -lt 10 ]; then - probability="0.00$probability" - elif [ $probability -lt 100 ]; then - probability="0.0$probability" - elif [ $probability -lt 1000 ]; then - probability="0.$probability" - else - probability="1" - fi - - probability="-m statistic --mode random --probability $probability" - - $IPT4 -I mwan3_policy_$policy \ - -m mark --mark 0x0/$MMX_MASK $probability \ - -m comment --comment "$iface $weight $total_weight_v4" \ - -j MARK --set-xmark $(mwan3_id2mask id MMX_MASK)/$MMX_MASK - fi - else - [ -n "$device" ] && { - $IPT4 -S mwan3_policy_$policy | grep -q '.*--comment ".* [0-9]* [0-9]*"' || \ - $IPT4 -I mwan3_policy_$policy \ - -o $device \ - -m mark --mark 0x0/$MMX_MASK \ - -m comment --comment "out $iface $device" \ - -j MARK --set-xmark $MMX_DEFAULT/$MMX_MASK - } - fi + if [ "$family" = "ipv4" ]; then + IPT="$IPT4" + elif [ "$family" = "ipv6" ]; then + IPT="$IPT6" fi - if [ "$family" == "ipv6" ]; then - - if [ "$(mwan3_get_iface_hotplug_state $iface)" = "online" ]; then - if [ "$metric" -lt "$lowest_metric_v6" ]; then - - total_weight_v6=$weight - $IPT6 -F mwan3_policy_$policy - $IPT6 -A mwan3_policy_$policy \ - -m mark --mark 0x0/$MMX_MASK \ - -m comment --comment "$iface $weight $weight" \ - -j MARK --set-xmark $(mwan3_id2mask id MMX_MASK)/$MMX_MASK - - lowest_metric_v6=$metric - - elif [ "$metric" -eq "$lowest_metric_v6" ]; then - - total_weight_v6=$(($total_weight_v6+$weight)) - probability=$(($weight*1000/$total_weight_v6)) - - if [ "$probability" -lt 10 ]; then - probability="0.00$probability" - elif [ $probability -lt 100 ]; then - probability="0.0$probability" - elif [ $probability -lt 1000 ]; then - probability="0.$probability" - else - probability="1" - fi - - probability="-m statistic --mode random --probability $probability" - - $IPT6 -I mwan3_policy_$policy \ - -m mark --mark 0x0/$MMX_MASK \ - $probability \ - -m comment --comment "$iface $weight $total_weight_v6" \ - -j MARK --set-xmark $(mwan3_id2mask id MMX_MASK)/$MMX_MASK - fi + if [ "$family" = "ipv4" ] && [ $is_offline -eq 0 ]; then + if [ "$metric" -lt "$lowest_metric_v4" ]; then + is_lowest=1 + total_weight_v4=$weight + lowest_metric_v4=$metric + elif [ "$metric" -eq "$lowest_metric_v4" ]; then + total_weight_v4=$(($total_weight_v4+$weight)) + total_weight=$total_weight_v4 else - [ -n "$device" ] && { - $IPT6 -S mwan3_policy_$policy | grep -q '.*--comment ".* [0-9]* [0-9]*"' || \ - $IPT6 -I mwan3_policy_$policy \ - -o $device \ - -m mark --mark 0x0/$MMX_MASK \ - -m comment --comment "out $iface $device" \ - -j MARK --set-xmark $MMX_DEFAULT/$MMX_MASK - } + return fi + elif [ "$family" = "ipv6" ] && [ $NO_IPV6 -eq 0 ] && [ $is_offline -eq 0 ]; then + if [ "$metric" -lt "$lowest_metric_v6" ]; then + is_lowest=1 + total_weight_v6=$weight + lowest_metric_v6=$metric + elif [ "$metric" -eq "$lowest_metric_v6" ]; then + total_weight_v6=$(($total_weight_v6+$weight)) + total_weight=$total_weight_v6 + else + return + fi + fi + if [ $is_lowest -eq 1 ]; then + $IPT -F "mwan3_policy_$policy" + $IPT -A "mwan3_policy_$policy" \ + -m mark --mark 0x0/$MMX_MASK \ + -m comment --comment "$iface $weight $weight" \ + -j MARK --set-xmark $(mwan3_id2mask id MMX_MASK)/$MMX_MASK + elif [ $is_offline -eq 0 ]; then + probability=$(($weight*1000/$total_weight)) + if [ "$probability" -lt 10 ]; then + probability="0.00$probability" + elif [ $probability -lt 100 ]; then + probability="0.0$probability" + elif [ $probability -lt 1000 ]; then + probability="0.$probability" + else + probability="1" + fi + + $IPT -I "mwan3_policy_$policy" \ + -m mark --mark 0x0/$MMX_MASK \ + -m statistic \ + --mode random \ + --probability "$probability" \ + -m comment --comment "$iface $weight $total_weight" \ + -j MARK --set-xmark $(mwan3_id2mask id MMX_MASK)/$MMX_MASK + elif [ -n "$device" ]; then + $IPT -S "mwan3_policy_$policy" | grep -q '.*--comment ".* [0-9]* [0-9]*"' || \ + $IPT -I "mwan3_policy_$policy" \ + -o "$device" \ + -m mark --mark 0x0/$MMX_MASK \ + -m comment --comment "out $iface $device" \ + -j MARK --set-xmark $MMX_DEFAULT/$MMX_MASK fi } @@ -802,35 +781,35 @@ mwan3_create_policies_iptables() policy="$1" - config_get last_resort $1 last_resort unreachable + config_get last_resort "$1" last_resort unreachable - if [ "$1" != $(echo "$1" | cut -c1-15) ]; then + if [ "$1" != "$(echo "$1" | cut -c1-15)" ]; then $LOG warn "Policy $1 exceeds max of 15 chars. Not setting policy" && return 0 fi for IPT in "$IPT4" "$IPT6"; do - - if ! $IPT -S mwan3_policy_$1 &> /dev/null; then - $IPT -N mwan3_policy_$1 + [ "$IPT" = "$IPT6" ] && [ $NO_IPV6 -ne 0 ] && continue + if ! $IPT -S "mwan3_policy_$1" &> /dev/null; then + $IPT -N "mwan3_policy_$1" fi - $IPT -F mwan3_policy_$1 + $IPT -F "mwan3_policy_$1" case "$last_resort" in blackhole) - $IPT -A mwan3_policy_$1 \ + $IPT -A "mwan3_policy_$1" \ -m mark --mark 0x0/$MMX_MASK \ -m comment --comment "blackhole" \ -j MARK --set-xmark $MMX_BLACKHOLE/$MMX_MASK ;; default) - $IPT -A mwan3_policy_$1 \ + $IPT -A "mwan3_policy_$1" \ -m mark --mark 0x0/$MMX_MASK \ -m comment --comment "default" \ -j MARK --set-xmark $MMX_DEFAULT/$MMX_MASK ;; *) - $IPT -A mwan3_policy_$1 \ + $IPT -A "mwan3_policy_$1" \ -m mark --mark 0x0/$MMX_MASK \ -m comment --comment "unreachable" \ -j MARK --set-xmark $MMX_UNREACHABLE/$MMX_MASK @@ -844,7 +823,7 @@ mwan3_create_policies_iptables() lowest_metric_v6=$DEFAULT_LOWEST_METRIC total_weight_v6=0 - config_list_foreach $1 use_member mwan3_set_policy + config_list_foreach "$1" use_member mwan3_set_policy } mwan3_set_policies_iptables() @@ -856,21 +835,22 @@ mwan3_set_sticky_iptables() { local id iface - for iface in $($IPT4 -S $policy | cut -s -d'"' -f2 | awk '{print $1}'); do + for iface in $($IPT4 -S "$policy" | cut -s -d'"' -f2 | awk '{print $1}'); do - if [ "$iface" == "$1" ]; then + if [ "$iface" = "$1" ]; then - mwan3_get_iface_id id $1 + mwan3_get_iface_id id "$1" [ -n "$id" ] || return 0 for IPT in "$IPT4" "$IPT6"; do - if [ -n "$($IPT -S mwan3_iface_in_$1 2> /dev/null)" ]; then - $IPT -I mwan3_rule_$rule \ + [ "$IPT" = "$IPT6" ] && [ $NO_IPV6 -ne 0 ] && continuea + if [ -n "$($IPT -S "mwan3_iface_in_$1" 2> /dev/null)" ]; then + $IPT -I "mwan3_rule_$rule" \ -m mark --mark $(mwan3_id2mask id MMX_MASK)/$MMX_MASK \ - -m set ! --match-set mwan3_sticky_$rule src,src \ + -m set ! --match-set "mwan3_sticky_$rule" src,src \ -j MARK --set-xmark 0x0/$MMX_MASK - $IPT -I mwan3_rule_$rule \ + $IPT -I "mwan3_rule_$rule" \ -m mark --mark 0/$MMX_MASK \ -j MARK --set-xmark $(mwan3_id2mask id MMX_MASK)/$MMX_MASK fi @@ -887,18 +867,18 @@ mwan3_set_user_iptables_rule() rule="$1" - config_get sticky $1 sticky 0 - config_get timeout $1 timeout 600 - config_get ipset $1 ipset - config_get proto $1 proto all - config_get src_ip $1 src_ip - config_get src_iface $1 src_iface - network_get_device src_dev $src_iface - config_get src_port $1 src_port - config_get dest_ip $1 dest_ip - config_get dest_port $1 dest_port - config_get use_policy $1 use_policy - config_get family $1 family any + config_get sticky "$1" sticky 0 + config_get timeout "$1" timeout 600 + config_get ipset "$1" ipset + config_get proto "$1" proto all + config_get src_ip "$1" src_ip + config_get src_iface "$1" src_iface + network_get_device src_dev "$src_iface" + config_get src_port "$1" src_port + config_get dest_ip "$1" dest_ip + config_get dest_port "$1" dest_port + config_get use_policy "$1" use_policy + config_get family "$1" family any [ -z "$dest_ip" ] && unset dest_ip [ -z "$src_ip" ] && unset src_ip @@ -916,11 +896,11 @@ mwan3_set_user_iptables_rule() unset dest_port } - config_get rule_logging $1 logging 0 + config_get rule_logging "$1" logging 0 config_get global_logging globals logging 0 config_get loglevel globals loglevel notice - if [ "$1" != $(echo "$1" | cut -c1-15) ]; then + if [ "$1" != "$(echo "$1" | cut -c1-15)" ]; then $LOG warn "Rule $1 exceeds max of 15 chars. Not setting rule" && return 0 fi @@ -929,11 +909,11 @@ mwan3_set_user_iptables_rule() fi if [ -n "$use_policy" ]; then - if [ "$use_policy" == "default" ]; then + if [ "$use_policy" = "default" ]; then policy="MARK --set-xmark $MMX_DEFAULT/$MMX_MASK" - elif [ "$use_policy" == "unreachable" ]; then + elif [ "$use_policy" = "unreachable" ]; then policy="MARK --set-xmark $MMX_UNREACHABLE/$MMX_MASK" - elif [ "$use_policy" == "blackhole" ]; then + elif [ "$use_policy" = "blackhole" ]; then policy="MARK --set-xmark $MMX_BLACKHOLE/$MMX_MASK" else if [ "$sticky" -eq 1 ]; then @@ -941,39 +921,41 @@ mwan3_set_user_iptables_rule() policy="mwan3_policy_$use_policy" for IPT in "$IPT4" "$IPT6"; do - if ! $IPT -S $policy &> /dev/null; then - $IPT -N $policy + [ "$IPT" = "$IPT6" ] && [ $NO_IPV6 -ne 0 ] && continue + if ! $IPT -S "$policy" &> /dev/null; then + $IPT -N "$policy" fi - if ! $IPT -S mwan3_rule_$1 &> /dev/null; then - $IPT -N mwan3_rule_$1 + if ! $IPT -S "mwan3_rule_$1" &> /dev/null; then + $IPT -N "mwan3_rule_$1" fi - $IPT -F mwan3_rule_$1 + $IPT -F "mwan3_rule_$1" done - $IPS -! create mwan3_sticky_v4_$rule \ - hash:ip,mark markmask $MMX_MASK \ - timeout $timeout - $IPS -! create mwan3_sticky_v6_$rule \ - hash:ip,mark markmask $MMX_MASK \ - timeout $timeout family inet6 - $IPS -! create mwan3_sticky_$rule list:set - $IPS -! add mwan3_sticky_$rule mwan3_sticky_v4_$rule - $IPS -! add mwan3_sticky_$rule mwan3_sticky_v6_$rule + $IPS -! create "mwan3_sticky_v4_$rule" \ + hash:ip,mark markmask "$MMX_MASK" \ + timeout "$timeout" + $IPS -! create "mwan3_sticky_v6_$rule" \ + hash:ip,mark markmask "$MMX_MASK" \ + timeout "$timeout" family inet6 + $IPS -! create "mwan3_sticky_$rule" list:set + $IPS -! add "mwan3_sticky_$rule" "mwan3_sticky_v4_$rule" + $IPS -! add "mwan3_sticky_$rule" "mwan3_sticky_v6_$rule" config_foreach mwan3_set_sticky_iptables interface for IPT in "$IPT4" "$IPT6"; do - $IPT -A mwan3_rule_$1 \ + [ "$IPT" = "$IPT6" ] && [ $NO_IPV6 -ne 0 ] && continue + $IPT -A "mwan3_rule_$1" \ -m mark --mark 0/$MMX_MASK \ - -j $policy - $IPT -A mwan3_rule_$1 \ + -j "$policy" + $IPT -A "mwan3_rule_$1" \ -m mark ! --mark 0xfc00/0xfc00 \ - -j SET --del-set mwan3_sticky_$rule src,src - $IPT -A mwan3_rule_$1 \ + -j SET --del-set "mwan3_sticky_$rule" src,src + $IPT -A "mwan3_rule_$1" \ -m mark ! --mark 0xfc00/0xfc00 \ - -j SET --add-set mwan3_sticky_$rule src,src + -j SET --add-set "mwan3_sticky_$rule" src,src done policy="mwan3_rule_$1" @@ -981,40 +963,42 @@ mwan3_set_user_iptables_rule() policy="mwan3_policy_$use_policy" for IPT in "$IPT4" "$IPT6"; do - if ! $IPT -S $policy &> /dev/null; then - $IPT -N $policy + [ "$IPT" = "$IPT6" ] && [ $NO_IPV6 -ne 0 ] && continue + if ! $IPT -S "$policy" &> /dev/null; then + $IPT -N "$policy" fi done fi fi for IPT in "$IPT4" "$IPT6"; do - [ "$family" == "ipv4" ] && [ "$IPT" == "$IPT6" ] && continue - [ "$family" == "ipv6" ] && [ "$IPT" == "$IPT4" ] && continue + [ "$IPT" = "$IPT6" ] && [ $NO_IPV6 -ne 0 ] && continue + [ "$family" = "ipv4" ] && [ "$IPT" = "$IPT6" ] && continue + [ "$family" = "ipv6" ] && [ "$IPT" = "$IPT4" ] && continue [ "$global_logging" = "1" ] && [ "$rule_logging" = "1" ] && { $IPT -A mwan3_rules \ - -p $proto \ + -p "$proto" \ ${src_ip:+-s} $src_ip \ ${src_dev:+-i} $src_dev \ - ${dest_ip:+-d} $dest_ip\ + ${dest_ip:+-d} $dest_ip \ $ipset \ ${src_port:+-m} ${src_port:+multiport} ${src_port:+--sports} $src_port \ ${dest_port:+-m} ${dest_port:+multiport} ${dest_port:+--dports} $dest_port \ -m mark --mark 0/$MMX_MASK \ -m comment --comment "$1" \ - -j LOG --log-level "$loglevel" --log-prefix "MWAN3($1)" &> /dev/null + -j LOG --log-level "$loglevel" --log-prefix "MWAN3($1)" } $IPT -A mwan3_rules \ - -p $proto \ + -p "$proto" \ ${src_ip:+-s} $src_ip \ ${src_dev:+-i} $src_dev \ - ${dest_ip:+-d} $dest_ip\ + ${dest_ip:+-d} $dest_ip \ $ipset \ ${src_port:+-m} ${src_port:+multiport} ${src_port:+--sports} $src_port \ ${dest_port:+-m} ${dest_port:+multiport} ${dest_port:+--dports} $dest_port \ -m mark --mark 0/$MMX_MASK \ - -j $policy &> /dev/null + -j $policy done fi } @@ -1024,7 +1008,7 @@ mwan3_set_user_rules() local IPT for IPT in "$IPT4" "$IPT6"; do - + [ "$IPT" = "$IPT6" ] && [ $NO_IPV6 -ne 0 ] && continue if ! $IPT -S mwan3_rules &> /dev/null; then $IPT -N mwan3_rules fi @@ -1039,47 +1023,58 @@ mwan3_set_iface_hotplug_state() { local iface=$1 local state=$2 - echo -n $state > $MWAN3_STATUS_DIR/iface_state/$iface + echo "$state" > "$MWAN3_STATUS_DIR/iface_state/$iface" } mwan3_get_iface_hotplug_state() { local iface=$1 - cat $MWAN3_STATUS_DIR/iface_state/$iface 2>/dev/null || echo "offline" + cat "$MWAN3_STATUS_DIR/iface_state/$iface" 2>/dev/null || echo "offline" } mwan3_report_iface_status() { local device result track_ips tracking IP IPT - mwan3_get_iface_id id $1 - network_get_device device $1 + mwan3_get_iface_id id "$1" + network_get_device device "$1" config_get enabled "$1" enabled 0 config_get family "$1" family ipv4 - if [ "$family" == "ipv4" ]; then + if [ "$family" = "ipv4" ]; then IP="$IP4" IPT="$IPT4" fi - if [ "$family" == "ipv6" ]; then + if [ "$family" = "ipv6" ]; then IP="$IP6" IPT="$IPT6" fi - if [ -z "$id" -o -z "$device" ]; then + if [ -z "$id" ] || [ -z "$device" ]; then result="offline" elif [ -n "$($IP rule | awk '$1 == "'$(($id+1000)):'"')" ] && \ [ -n "$($IP rule | awk '$1 == "'$(($id+2000)):'"')" ] && \ [ -n "$($IPT -S mwan3_iface_in_$1 2> /dev/null)" ] && \ [ -n "$($IP route list table $id default dev $device 2> /dev/null)" ]; then - result="$(mwan3_get_iface_hotplug_state $1)" + json_init + json_add_string section interfaces + json_add_string interface "$1" + json_load "$(ubus call mwan3 status "$(json_dump)")" + json_select "interfaces" + json_select "$1" + json_get_vars online uptime + json_select .. + json_select .. + online="$(printf '%02dh:%02dm:%02ds\n' $(($online/3600)) $(($online%3600/60)) $(($online%60)))" + uptime="$(printf '%02dh:%02dm:%02ds\n' $(($uptime/3600)) $(($uptime%3600/60)) $(($uptime%60)))" + result="$(mwan3_get_iface_hotplug_state $1) $online, uptime $uptime" elif [ -n "$($IP rule | awk '$1 == "'$(($id+1000)):'"')" ] || \ [ -n "$($IP rule | awk '$1 == "'$(($id+2000)):'"')" ] || \ [ -n "$($IPT -S mwan3_iface_in_$1 2> /dev/null)" ] || \ [ -n "$($IP route list table $id default dev $device 2> /dev/null)" ]; then result="error" - elif [ "$enabled" == "1" ]; then + elif [ "$enabled" = "1" ]; then result="offline" else result="disabled" @@ -1089,7 +1084,7 @@ mwan3_report_iface_status() { track_ips="$1 $track_ips" } - config_list_foreach $1 track_ip mwan3_list_track_ips + config_list_foreach "$1" track_ip mwan3_list_track_ips if [ -n "$track_ips" ]; then if [ -n "$(pgrep -f "mwan3track $1 $device")" ]; then @@ -1111,16 +1106,16 @@ mwan3_report_policies() local percent total_weight weight iface - total_weight=$($ipt -S $policy | grep -v '.*--comment "out .*" .*$' | cut -s -d'"' -f2 | head -1 | awk '{print $3}') + total_weight=$($ipt -S "$policy" | grep -v '.*--comment "out .*" .*$' | cut -s -d'"' -f2 | head -1 | awk '{print $3}') if [ ! -z "${total_weight##*[!0-9]*}" ]; then - for iface in $($ipt -S $policy | grep -v '.*--comment "out .*" .*$' | cut -s -d'"' -f2 | awk '{print $1}'); do - weight=$($ipt -S $policy | grep -v '.*--comment "out .*" .*$' | cut -s -d'"' -f2 | awk '$1 == "'$iface'"' | awk '{print $2}') + for iface in $($ipt -S "$policy" | grep -v '.*--comment "out .*" .*$' | cut -s -d'"' -f2 | awk '{print $1}'); do + weight=$($ipt -S "$policy" | grep -v '.*--comment "out .*" .*$' | cut -s -d'"' -f2 | awk '$1 == "'$iface'"' | awk '{print $2}') percent=$(($weight*100/$total_weight)) echo " $iface ($percent%)" done else - echo " $($ipt -S $policy | grep -v '.*--comment "out .*" .*$' | sed '/.*--comment \([^ ]*\) .*$/!d;s//\1/;q')" + echo " $($ipt -S "$policy" | grep -v '.*--comment "out .*" .*$' | sed '/.*--comment \([^ ]*\) .*$/!d;s//\1/;q')" fi } @@ -1146,8 +1141,6 @@ mwan3_report_policies_v6() mwan3_report_connected_v4() { - local address - if [ -n "$($IPT4 -S mwan3_connected 2> /dev/null)" ]; then $IPS -o save list mwan3_connected_v4 | grep add | cut -d " " -f 3 fi @@ -1155,8 +1148,6 @@ mwan3_report_connected_v4() mwan3_report_connected_v6() { - local address - if [ -n "$($IPT6 -S mwan3_connected 2> /dev/null)" ]; then $IPS -o save list mwan3_connected_v6 | grep add | cut -d " " -f 3 fi diff --git a/mwan3/files/usr/sbin/mwan3 b/mwan3/files/usr/sbin/mwan3 index a854dfda2..79a0eba25 100755 --- a/mwan3/files/usr/sbin/mwan3 +++ b/mwan3/files/usr/sbin/mwan3 @@ -45,30 +45,39 @@ ifup() { local device enabled up l3_device status + mwan3_lock "command" "mwan3" + config_load mwan3 config_get_bool enabled globals 'enabled' 0 + [ ${enabled} -gt 0 ] || { echo "The service mwan3 is global disabled." echo "Please execute \"/etc/init.d/mwan3 start\" first." + mwan3_unlock "command" "mwan3" exit 1 } if [ -z "$1" ]; then - echo "Expecting interface. Usage: mwan3 ifup " && exit 0 + echo "Expecting interface. Usage: mwan3 ifup " + mwan3_unlock "command" "mwan3" + exit 0 fi if [ -n "$2" ]; then - echo "Too many arguments. Usage: mwan3 ifup " && exit 0 + echo "Too many arguments. Usage: mwan3 ifup " + mwan3_unlock "command" "mwan3" + exit 0 fi + config_get enabled "$1" enabled 0 + mwan3_unlock "command" "mwan3" + status=$(ubus -S call network.interface.$1 status) [ -n "$status" ] && { json_load "$status" - json_get_vars up l3_device + json_get_vars up l3_device } - config_get enabled "$1" enabled 0 - if [ "$up" = "1" ] \ && [ -n "$l3_device" ] \ && [ "$enabled" = "1" ]; then @@ -90,6 +99,7 @@ policies() echo "Current ipv4 policies:" mwan3_report_policies_v4 echo -e + [ $NO_IPV6 -ne 0 ] && return echo "Current ipv6 policies:" mwan3_report_policies_v6 echo -e @@ -100,6 +110,7 @@ connected() echo "Directly connected ipv4 networks:" mwan3_report_connected_v4 echo -e + [ $NO_IPV6 -ne 0 ] && return echo "Directly connected ipv6 networks:" mwan3_report_connected_v6 echo -e @@ -110,6 +121,7 @@ rules() echo "Active ipv4 user rules:" mwan3_report_rules_v4 echo -e + [ $NO_IPV6 -ne 0 ] && return echo "Active ipv6 user rules:" mwan3_report_rules_v6 echo -e @@ -127,7 +139,9 @@ start() { local enabled + mwan3_lock "command" "mwan3" uci_toggle_state mwan3 globals enabled "1" + mwan3_unlock "command" "mwan3" config_load mwan3 config_foreach ifup interface @@ -138,16 +152,23 @@ stop() local ipset route rule table IP IPT pid mwan3_lock "command" "mwan3" + uci_toggle_state mwan3 globals enabled "0" for pid in $(pgrep -f "mwan3rtmon"); do kill -TERM "$pid" > /dev/null 2>&1 - sleep 1 - kill -KILL "$pid" > /dev/null 2>&1 done for pid in $(pgrep -f "mwan3track"); do kill -TERM "$pid" > /dev/null 2>&1 - sleep 1 + done + + sleep 1 + + for pid in $(pgrep -f "mwan3rtmon"); do + kill -KILL "$pid" > /dev/null 2>&1 + done + + for pid in $(pgrep -f "mwan3track"); do kill -KILL "$pid" > /dev/null 2>&1 done @@ -155,7 +176,7 @@ stop() config_foreach mwan3_track_clean interface for IP in "$IP4" "$IP6"; do - + [ "$IP" = "$IP6" ] && [ $NO_IPV6 -ne 0 ] && continue for route in $(seq 1 $MWAN3_INTERFACE_MAX); do $IP route flush table $route &> /dev/null done @@ -166,7 +187,7 @@ stop() done for IPT in "$IPT4" "$IPT6"; do - + [ "$IPT" = "$IPT6" ] && [ $NO_IPV6 -ne 0 ] && continue $IPT -D PREROUTING -j mwan3_hook &> /dev/null $IPT -D OUTPUT -j mwan3_hook &> /dev/null @@ -189,10 +210,7 @@ stop() mwan3_unlock "command" "mwan3" - mwan3_lock_clean rm -rf $MWAN3_STATUS_DIR $MWAN3TRACK_STATUS_DIR - - uci_toggle_state mwan3 globals enabled "0" } restart() {