mwan3:bump to new version

This commit is contained in:
coolsnowwolf 2020-07-02 13:30:19 +08:00
parent 0c33bb3dcb
commit b9ef38874c
12 changed files with 817 additions and 330 deletions

View File

@ -8,10 +8,10 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=mwan3
PKG_VERSION:=2.6.18
PKG_VERSION:=2.8.7
PKG_RELEASE:=1
PKG_MAINTAINER:=Florian Eckert <fe@dev.tdt.de>
PKG_LICENSE:=GPLv2
PKG_LICENSE:=GPL-2.0
include $(INCLUDE_DIR)/package.mk

View File

@ -1,12 +1,14 @@
config globals 'globals'
option mmx_mask '0x3F00'
option local_source 'lan'
option rtmon_interval '5'
config interface 'wan'
option enabled '1'
list track_ip '114.114.114.114'
list track_ip '114.114.115.115'
list track_ip '8.8.4.4'
list track_ip '8.8.8.8'
list track_ip '208.67.222.222'
list track_ip '208.67.220.220'
option family 'ipv4'
option reliability '2'
option count '1'
@ -19,14 +21,117 @@ config interface 'wan'
option down '3'
option up '8'
config interface 'wan6'
option enabled '0'
list track_ip '2001:4860:4860::8844'
list track_ip '2001:4860:4860::8888'
list track_ip '2620:0:ccd::2'
list track_ip '2620:0:ccc::2'
option family 'ipv6'
option reliability '2'
option count '1'
option timeout '2'
option interval '5'
option down '3'
option up '8'
config interface 'wanb'
option enabled '0'
list track_ip '8.8.4.4'
list track_ip '8.8.8.8'
list track_ip '208.67.222.222'
list track_ip '208.67.220.220'
option family 'ipv4'
option reliability '1'
option count '1'
option timeout '2'
option failure_latency '1000'
option recovery_latency '500'
option failure_loss '20'
option recovery_loss '5'
option interval '5'
option down '3'
option up '8'
config interface 'wanb6'
option enabled '0'
list track_ip '2001:4860:4860::8844'
list track_ip '2001:4860:4860::8888'
list track_ip '2620:0:ccd::2'
list track_ip '2620:0:ccc::2'
option family 'ipv6'
option reliability '1'
option count '1'
option timeout '2'
option interval '5'
option down '3'
option up '8'
config member 'wan_m1_w3'
option interface 'wan'
option metric '1'
option weight '3'
config policy 'balanced'
option last_resort 'unreachable'
config member 'wan_m2_w3'
option interface 'wan'
option metric '2'
option weight '3'
config member 'wanb_m1_w2'
option interface 'wanb'
option metric '1'
option weight '2'
config member 'wanb_m2_w2'
option interface 'wanb'
option metric '2'
option weight '2'
config member 'wan6_m1_w3'
option interface 'wan6'
option metric '1'
option weight '3'
config member 'wan6_m2_w3'
option interface 'wan6'
option metric '2'
option weight '3'
config member 'wanb6_m1_w2'
option interface 'wanb6'
option metric '1'
option weight '2'
config member 'wanb6_m2_w2'
option interface 'wanb6'
option metric '2'
option weight '2'
config policy 'wan_only'
list use_member 'wan_m1_w3'
list use_member 'wan6_m1_w3'
config policy 'wanb_only'
list use_member 'wanb_m1_w2'
list use_member 'wanb6_m1_w2'
config policy 'balanced'
list use_member 'wan_m1_w3'
list use_member 'wanb_m1_w2'
list use_member 'wan6_m1_w3'
list use_member 'wanb6_m1_w2'
config policy 'wan_wanb'
list use_member 'wan_m1_w3'
list use_member 'wanb_m2_w2'
list use_member 'wan6_m1_w3'
list use_member 'wanb6_m2_w2'
config policy 'wanb_wan'
list use_member 'wan_m2_w3'
list use_member 'wanb_m1_w2'
list use_member 'wan6_m2_w3'
list use_member 'wanb6_m1_w2'
config rule 'https'
option sticky '1'

View File

@ -1,48 +0,0 @@
#!/bin/sh
. /lib/functions.sh
. /lib/mwan3/mwan3.sh
. /lib/functions/network.sh
[ "$ACTION" = "ifup" -o "$ACTION" = "ifdown" ] || exit 1
[ -n "$INTERFACE" ] || exit 2
if [ "$ACTION" = "ifup" ]; then
[ -n "$DEVICE" ] || exit 3
fi
config_load mwan3
config_get_bool enabled globals 'enabled' '0'
[ ${enabled} -gt 0 ] || exit 0
config_get local_source globals local_source 'none'
[ "${local_source}" = "none" ] && {
exit 0
}
[ "${local_source}" = "$INTERFACE" ] || {
exit 0
}
mwan3_lock
src_ip=$(uci_get_state mwan3 globals src_ip)
[ "${src_ip}" != "" ] && {
ip route del default via "${src_ip}" dev lo 1>/dev/null 2>&1
ip addr del "${src_ip}/32" dev lo 1>/dev/null 2>&1
}
sleep 1
[ "$ACTION" = "ifup" ] && {
network_get_ipaddr src_ip "${local_source}"
if [ "${src_ip}" = "" ]; then
$LOG warn "Unable to set source ip for own initiated traffic (${local_source})"
else
ip addr add "${src_ip}/32" dev lo
ip route add default via "${src_ip}" dev lo
uci_toggle_state mwan3 globals src_ip "${src_ip}"
fi
}
mwan3_unlock
exit 0

View File

@ -16,10 +16,11 @@ config_load mwan3
config_get_bool enabled globals 'enabled' '0'
[ ${enabled} -gt 0 ] || exit 0
mwan3_lock
mwan3_lock "$ACTION" "$INTERFACE"
mwan3_init
mwan3_set_connected_iptables
mwan3_unlock
mwan3_set_custom_ipset
mwan3_unlock "$ACTION" "$INTERFACE"
config_get enabled $INTERFACE enabled 0
config_get initial_state $INTERFACE initial_state "online"
@ -57,7 +58,7 @@ else
running=1
fi
mwan3_lock
mwan3_lock "$ACTION" "$INTERFACE"
$LOG notice "Execute "$ACTION" event on interface $INTERFACE (${DEVICE:-unknown})"
case "$ACTION" in
@ -71,14 +72,13 @@ case "$ACTION" in
$LOG notice "Starting tracker on interface $INTERFACE (${DEVICE:-unknown})"
mwan3_set_iface_hotplug_state $INTERFACE "online"
mwan3_track $INTERFACE $DEVICE "online" "$src_ip"
mwan3_set_policies_iptables
mwan3_set_user_rules
mwan3_flush_conntrack $INTERFACE $DEVICE "ifup"
else
$LOG notice "Starting tracker on interface $INTERFACE (${DEVICE:-unknown})"
mwan3_set_iface_hotplug_state $INTERFACE "offline"
mwan3_track $INTERFACE $DEVICE "unknown" "$src_ip"
mwan3_track $INTERFACE $DEVICE "offline" "$src_ip"
fi
mwan3_set_policies_iptables
mwan3_set_user_rules
;;
ifdown)
mwan3_set_iface_hotplug_state $INTERFACE "offline"
@ -86,10 +86,9 @@ case "$ACTION" in
mwan3_track_signal $INTERFACE $DEVICE
mwan3_set_policies_iptables
mwan3_set_user_rules
mwan3_flush_conntrack $INTERFACE $DEVICE "ifdown"
;;
esac
mwan3_unlock
mwan3_unlock "$ACTION" "$INTERFACE"
exit 0

View File

@ -0,0 +1,22 @@
#!/bin/sh
. /lib/functions.sh
. /lib/functions/network.sh
. /lib/mwan3/mwan3.sh
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
mwan3_unlock "$ACTION" "mwan3rtmon"
fi
config_get enabled $INTERFACE enabled 0
[ "${enabled}" = "0" ] || {
mwan3_flush_conntrack "$INTERFACE" "$ACTION"
}
exit 0

View File

@ -1,32 +1,28 @@
#!/bin/sh /etc/rc.common
START=19
reload() {
local enabled
config_load mwan3
config_get_bool enabled globals 'enabled' 0
[ ${enabled} -gt 0 ] || {
echo "Warning: mwan3 is global disabled. Usage: /etc/init.d/mwan3 start"
exit 0
}
mwan3 restart
}
USE_PROCD=1
boot() {
. /lib/config/uci.sh
uci_toggle_state mwan3 globals enabled "1"
mwan3_boot=1
rc_procd start_service
}
start() {
. /lib/config/uci.sh
uci_toggle_state mwan3 globals enabled "1"
mwan3 start
reload_service() {
/usr/sbin/mwan3 restart
}
stop() {
. /lib/config/uci.sh
uci_toggle_state mwan3 globals enabled "0"
mwan3 stop
start_service() {
[ -n "${mwan3_boot}" ] && return 0
/usr/sbin/mwan3 start
}
stop_service() {
/usr/sbin/mwan3 stop
}
service_triggers() {
procd_add_reload_trigger 'mwan3'
}

View File

@ -0,0 +1,26 @@
#!/bin/sh
. /lib/functions.sh
mwan3_migrate_flush_conntrack() {
local iface="$1"
config_get value "${iface}" flush_conntrack
case $value in
always)
uci_remove mwan3 "$iface" flush_conntrack
uci_add_list mwan3 "$iface" flush_conntrack ifup
uci_add_list mwan3 "$iface" flush_conntrack ifdown
;;
never)
uci_remove mwan3 "$iface" flush_conntrack
;;
esac
uci_commit mwan3
}
config_load mwan3
config_foreach mwan3_migrate_flush_conntrack interface
exit 0

View File

@ -7,6 +7,18 @@ IPT4="iptables -t mangle -w"
IPT6="ip6tables -t mangle -w"
LOG="logger -t mwan3[$$] -p"
CONNTRACK_FILE="/proc/net/nf_conntrack"
IPv6_REGEX="([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|"
IPv6_REGEX="${IPv6_REGEX}([0-9a-fA-F]{1,4}:){1,7}:|"
IPv6_REGEX="${IPv6_REGEX}([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|"
IPv6_REGEX="${IPv6_REGEX}([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|"
IPv6_REGEX="${IPv6_REGEX}([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|"
IPv6_REGEX="${IPv6_REGEX}([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|"
IPv6_REGEX="${IPv6_REGEX}([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|"
IPv6_REGEX="${IPv6_REGEX}[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|"
IPv6_REGEX="${IPv6_REGEX}:((:[0-9a-fA-F]{1,4}){1,7}|:)|"
IPv6_REGEX="${IPv6_REGEX}fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|"
IPv6_REGEX="${IPv6_REGEX}::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|"
IPv6_REGEX="${IPv6_REGEX}([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])"
MWAN3_STATUS_DIR="/var/run/mwan3"
MWAN3TRACK_STATUS_DIR="/var/run/mwan3track"
@ -20,6 +32,71 @@ MM_BLACKHOLE=""
MMX_UNREACHABLE=""
MM_UNREACHABLE=""
# 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=""
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)
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
$IP4 route del table $tid $line
done
cat /tmp/mwan3rtmon/ipv4.main | grep -v -x -F -f /tmp/mwan3rtmon/ipv4.$tid | while read line; do
$IP4 route add table $tid $line
done
fi
}
if [ "$(uci get mwan3.@interface[$((idx-1))].enabled)" = "1" ]; then
ret=0
fi
done
rm -f /tmp/mwan3rtmon/ipv4.*
return $ret
}
# return true(=0) if has any mwan3 interface enabled
# otherwise return false
mwan3_rtmon_ipv6()
{
local tid=1
local idx=0
local ret=1
local tbl=""
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)
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
$IP6 route del table $tid $line
done
cat /tmp/mwan3rtmon/ipv6.main | grep -v -x -F -f /tmp/mwan3rtmon/ipv6.$tid | while read line; do
$IP6 route add table $tid $line
done
fi
}
if [ "$(uci get mwan3.@interface[$((idx-1))].enabled)" = "1" ]; then
ret=0
fi
done
rm -f /tmp/mwan3rtmon/ipv6.*
return $ret
}
# counts how many bits are set to 1
# n&(n-1) clears the lowest bit set to 1
@ -94,9 +171,11 @@ mwan3_init()
mwan3_lock() {
lock /var/run/mwan3.lock
# $LOG debug "$1 $2 (lock)"
}
mwan3_unlock() {
# $LOG debug "$1 $2 (unlock)"
lock -u /var/run/mwan3.lock
}
@ -119,9 +198,49 @@ mwan3_get_iface_id()
export "$1=$_tmp"
}
mwan3_set_custom_ipset_v4()
{
local custom_network_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
done
}
mwan3_set_custom_ipset_v6()
{
local custom_network_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
done
}
mwan3_set_custom_ipset()
{
$IPS -! create mwan3_custom_v4 hash:net
$IPS create mwan3_custom_v4_temp hash:net
config_list_foreach "globals" "rt_table_lookup" mwan3_set_custom_ipset_v4
$IPS swap mwan3_custom_v4_temp mwan3_custom_v4
$IPS destroy mwan3_custom_v4_temp
$IPS -! create mwan3_custom_v6 hash:net family inet6
$IPS create mwan3_custom_v6_temp hash:net family inet6
config_list_foreach "globals" "rt_table_lookup" mwan3_set_custom_ipset_v6
$IPS swap mwan3_custom_v6_temp mwan3_custom_v6
$IPS destroy mwan3_custom_v6_temp
$IPS -! create mwan3_connected list:set
$IPS -! add mwan3_connected mwan3_custom_v4
$IPS -! add mwan3_connected mwan3_custom_v6
}
mwan3_set_connected_iptables()
{
local connected_network_v4 connected_network_v6
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
@ -142,7 +261,7 @@ mwan3_set_connected_iptables()
$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 '([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])'); do
for connected_network_v6 in $($IP6 route | awk '{print $1}' | egrep "$IPv6_REGEX"); do
$IPS -! add mwan3_connected_v6_temp $connected_network_v6
done
@ -152,6 +271,20 @@ mwan3_set_connected_iptables()
$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
$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
}
mwan3_set_general_rules()
@ -185,11 +318,9 @@ mwan3_set_general_iptables()
if ! $IPT -S mwan3_connected &> /dev/null; then
$IPT -N mwan3_connected
$IPS -! create mwan3_connected list:set
$IPT -A mwan3_connected -m set --match-set mwan3_connected dst -j MARK --set-xmark $MMX_DEFAULT/$MMX_MASK
fi
if ! $IPT -S mwan3_ifaces_out &> /dev/null; then
$IPT -N mwan3_ifaces_out
$IPT -A mwan3_connected \
-m set --match-set mwan3_connected dst \
-j MARK --set-xmark $MMX_DEFAULT/$MMX_MASK
fi
if ! $IPT -S mwan3_rules &> /dev/null; then
@ -200,19 +331,50 @@ mwan3_set_general_iptables()
$IPT -N mwan3_hook
# do not mangle ipv6 ra service
if [ "$IPT" = "$IPT6" ]; then
$IPT6 -A mwan3_hook -p ipv6-icmp -m icmp6 --icmpv6-type 133 -j RETURN
$IPT6 -A mwan3_hook -p ipv6-icmp -m icmp6 --icmpv6-type 134 -j RETURN
$IPT6 -A mwan3_hook -p ipv6-icmp -m icmp6 --icmpv6-type 135 -j RETURN
$IPT6 -A mwan3_hook -p ipv6-icmp -m icmp6 --icmpv6-type 136 -j RETURN
$IPT6 -A mwan3_hook -p ipv6-icmp -m icmp6 --icmpv6-type 137 -j RETURN
$IPT6 -A mwan3_hook \
-p ipv6-icmp \
-m icmp6 --icmpv6-type 133 \
-j RETURN
$IPT6 -A mwan3_hook \
-p ipv6-icmp \
-m icmp6 --icmpv6-type 134 \
-j RETURN
$IPT6 -A mwan3_hook \
-p ipv6-icmp \
-m icmp6 --icmpv6-type 135 \
-j RETURN
$IPT6 -A mwan3_hook \
-p ipv6-icmp \
-m icmp6 --icmpv6-type 136 \
-j RETURN
$IPT6 -A mwan3_hook \
-p ipv6-icmp \
-m icmp6 --icmpv6-type 137 \
-j RETURN
# do not mangle outgoing echo request
$IPT6 -A mwan3_hook \
-m set --match-set mwan3_source_v6 src \
-p ipv6-icmp \
-m icmp6 --icmpv6-type 128 \
-j RETURN
fi
$IPT -A mwan3_hook -j CONNMARK --restore-mark --nfmask $MMX_MASK --ctmask $MMX_MASK
$IPT -A mwan3_hook -m mark --mark 0x0/$MMX_MASK -j mwan3_ifaces_in
$IPT -A mwan3_hook -m mark --mark 0x0/$MMX_MASK -j mwan3_connected
$IPT -A mwan3_hook -m mark --mark 0x0/$MMX_MASK -j mwan3_ifaces_out
$IPT -A mwan3_hook -m mark --mark 0x0/$MMX_MASK -j mwan3_rules
$IPT -A mwan3_hook -j CONNMARK --save-mark --nfmask $MMX_MASK --ctmask $MMX_MASK
$IPT -A mwan3_hook -m mark ! --mark $MMX_DEFAULT/$MMX_MASK -j mwan3_connected
$IPT -A mwan3_hook \
-j CONNMARK --restore-mark --nfmask $MMX_MASK --ctmask $MMX_MASK
$IPT -A mwan3_hook \
-m mark --mark 0x0/$MMX_MASK \
-j mwan3_ifaces_in
$IPT -A mwan3_hook \
-m mark --mark 0x0/$MMX_MASK \
-j mwan3_connected
$IPT -A mwan3_hook \
-m mark --mark 0x0/$MMX_MASK \
-j mwan3_rules
$IPT -A mwan3_hook \
-j CONNMARK --save-mark --nfmask $MMX_MASK --ctmask $MMX_MASK
$IPT -A mwan3_hook \
-m mark ! --mark $MMX_DEFAULT/$MMX_MASK \
-j mwan3_connected
fi
if ! $IPT -S PREROUTING | grep mwan3_hook &> /dev/null; then
@ -241,30 +403,29 @@ mwan3_create_iface_iptables()
$IPT4 -N mwan3_ifaces_in
fi
if ! $IPT4 -S mwan3_ifaces_out &> /dev/null; then
$IPT4 -N mwan3_ifaces_out
fi
if ! $IPT4 -S mwan3_iface_in_$1 &> /dev/null; then
$IPT4 -N mwan3_iface_in_$1
fi
if ! $IPT4 -S mwan3_iface_out_$1 &> /dev/null; then
$IPT4 -N mwan3_iface_out_$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 -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
$IPT4 -F mwan3_iface_out_$1
$IPT4 -A mwan3_iface_out_$1 -o $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_out -m mark --mark 0x0/$MMX_MASK -j mwan3_iface_out_$1 &> /dev/null
$IPT4 -A mwan3_ifaces_out -m mark --mark 0x0/$MMX_MASK -j mwan3_iface_out_$1
$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
fi
if [ "$family" == "ipv6" ]; then
@ -274,30 +435,26 @@ mwan3_create_iface_iptables()
$IPT6 -N mwan3_ifaces_in
fi
if ! $IPT6 -S mwan3_ifaces_out &> /dev/null; then
$IPT6 -N mwan3_ifaces_out
fi
if ! $IPT6 -S mwan3_iface_in_$1 &> /dev/null; then
$IPT6 -N mwan3_iface_in_$1
fi
if ! $IPT6 -S mwan3_iface_out_$1 &> /dev/null; then
$IPT6 -N mwan3_iface_out_$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 -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
$IPT6 -F mwan3_iface_out_$1
$IPT6 -A mwan3_iface_out_$1 -o $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_out -m mark --mark 0x0/$MMX_MASK -j mwan3_iface_out_$1 &> /dev/null
$IPT6 -A mwan3_ifaces_out -m mark --mark 0x0/$MMX_MASK -j mwan3_iface_out_$1
$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
fi
}
@ -307,30 +464,26 @@ mwan3_delete_iface_iptables()
if [ "$family" == "ipv4" ]; then
$IPT4 -D mwan3_ifaces_in -m mark --mark 0x0/$MMX_MASK -j mwan3_iface_in_$1 &> /dev/null
$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
$IPT4 -D mwan3_ifaces_out -m mark --mark 0x0/$MMX_MASK -j mwan3_iface_out_$1 &> /dev/null
$IPT4 -F mwan3_iface_out_$1 &> /dev/null
$IPT4 -X mwan3_iface_out_$1 &> /dev/null
fi
if [ "$family" == "ipv6" ]; then
$IPT6 -D mwan3_ifaces_in -m mark --mark 0x0/$MMX_MASK -j mwan3_iface_in_$1 &> /dev/null
$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
$IPT6 -D mwan3_ifaces_out -m mark --mark 0x0/$MMX_MASK -j mwan3_iface_out_$1 &> /dev/null
$IPT6 -F mwan3_iface_out_$1 &> /dev/null
$IPT6 -X mwan3_iface_out_$1 &> /dev/null
fi
}
mwan3_create_iface_route()
{
local id route_args
local id route_args metric
config_get family $1 family ipv4
mwan3_get_iface_id id $1
@ -350,8 +503,14 @@ mwan3_create_iface_route()
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
fi
if [ "$family" == "ipv6" ]; then
@ -367,8 +526,14 @@ mwan3_create_iface_route()
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
fi
}
@ -409,7 +574,7 @@ mwan3_create_iface_rules()
$IP4 rule del pref $(($id+2000))
done
$IP4 rule add pref $(($id+1000)) iif $2 lookup main
$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
@ -423,7 +588,7 @@ mwan3_create_iface_rules()
$IP6 rule del pref $(($id+2000))
done
$IP6 rule add pref $(($id+1000)) iif $2 lookup main
$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
}
@ -475,6 +640,16 @@ mwan3_delete_iface_ipset_entries()
done
}
mwan3_rtmon()
{
pid="$(pgrep -f mwan3rtmon)"
if [ "${pid}" != "" ]; then
kill -USR1 "${pid}"
else
[ -x /usr/sbin/mwan3rtmon ] && /usr/sbin/mwan3rtmon &
fi
}
mwan3_track()
{
local track_ip track_ips pid
@ -507,13 +682,14 @@ mwan3_track_signal()
mwan3_set_policy()
{
local iface_count id iface family metric probability weight
local iface_count id iface family metric probability weight device
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
[ "$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
@ -529,7 +705,10 @@ mwan3_set_policy()
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
$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
@ -550,8 +729,20 @@ mwan3_set_policy()
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
$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
fi
@ -562,7 +753,10 @@ mwan3_set_policy()
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
$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
@ -583,8 +777,21 @@ mwan3_set_policy()
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
$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
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
}
fi
fi
}
@ -611,13 +818,22 @@ mwan3_create_policies_iptables()
case "$last_resort" in
blackhole)
$IPT -A mwan3_policy_$1 -m mark --mark 0x0/$MMX_MASK -m comment --comment "blackhole" -j MARK --set-xmark $MMX_BLACKHOLE/$MMX_MASK
$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 -m mark --mark 0x0/$MMX_MASK -m comment --comment "default" -j MARK --set-xmark $MMX_DEFAULT/$MMX_MASK
$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 -m mark --mark 0x0/$MMX_MASK -m comment --comment "unreachable" -j MARK --set-xmark $MMX_UNREACHABLE/$MMX_MASK
$IPT -A mwan3_policy_$1 \
-m mark --mark 0x0/$MMX_MASK \
-m comment --comment "unreachable" \
-j MARK --set-xmark $MMX_UNREACHABLE/$MMX_MASK
;;
esac
done
@ -649,9 +865,14 @@ mwan3_set_sticky_iptables()
[ -n "$id" ] || return 0
for IPT in "$IPT4" "$IPT6"; do
if [ -n "$($IPT -S mwan3_iface_in_$1 2> /dev/null)" -a -n "$($IPT -S mwan3_iface_out_$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 -j MARK --set-xmark 0x0/$MMX_MASK
$IPT -I mwan3_rule_$rule -m mark --mark 0/$MMX_MASK -j MARK --set-xmark $(mwan3_id2mask id MMX_MASK)/$MMX_MASK
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 \
-j MARK --set-xmark 0x0/$MMX_MASK
$IPT -I mwan3_rule_$rule \
-m mark --mark 0/$MMX_MASK \
-j MARK --set-xmark $(mwan3_id2mask id MMX_MASK)/$MMX_MASK
fi
done
fi
@ -660,7 +881,9 @@ mwan3_set_sticky_iptables()
mwan3_set_user_iptables_rule()
{
local ipset family proto policy src_ip src_port sticky dest_ip dest_port use_policy timeout rule policy IPT
local ipset family proto policy src_ip src_port src_iface src_dev
local sticky dest_ip dest_port use_policy timeout rule policy IPT
local global_logging rule_logging loglevel
rule="$1"
@ -668,13 +891,35 @@ mwan3_set_user_iptables_rule()
config_get timeout $1 timeout 600
config_get ipset $1 ipset
config_get proto $1 proto all
config_get src_ip $1 src_ip 0.0.0.0/0
config_get src_port $1 src_port 0:65535
config_get dest_ip $1 dest_ip 0.0.0.0/0
config_get dest_port $1 dest_port 0:65535
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
[ -z "$ipset" ] && unset ipset
[ -z "$src_port" ] && unset src_port
[ -z "$dest_port" ] && unset dest_port
[ "$proto" != 'tcp' ] && [ "$proto" != 'udp' ] && {
[ -n "$src_port" ] && {
$LOG warn "src_port set to '$src_port' but proto set to '$proto' not tcp or udp. src_port will be ignored"
}
[ -n "$dest_port" ] && {
$LOG warn "dest_port set to '$dest_port' but proto set to '$proto' not tcp or udp. dest_port will be ignored"
}
unset src_port
unset dest_port
}
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
$LOG warn "Rule $1 exceeds max of 15 chars. Not setting rule" && return 0
fi
@ -707,8 +952,12 @@ mwan3_set_user_iptables_rule()
$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_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
@ -716,9 +965,15 @@ mwan3_set_user_iptables_rule()
config_foreach mwan3_set_sticky_iptables interface
for IPT in "$IPT4" "$IPT6"; do
$IPT -A mwan3_rule_$1 -m mark --mark 0/$MMX_MASK -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 -m mark ! --mark 0xfc00/0xfc00 -j SET --add-set mwan3_sticky_$rule src,src
$IPT -A mwan3_rule_$1 \
-m mark --mark 0/$MMX_MASK \
-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 \
-m mark ! --mark 0xfc00/0xfc00 \
-j SET --add-set mwan3_sticky_$rule src,src
done
policy="mwan3_rule_$1"
@ -733,42 +988,34 @@ mwan3_set_user_iptables_rule()
fi
fi
for IPT in "$IPT4" "$IPT6"; do
[ "$family" == "ipv4" ] && [ "$IPT" == "$IPT6" ] && continue
[ "$family" == "ipv6" ] && [ "$IPT" == "$IPT4" ] && continue
[ "$global_logging" = "1" ] && [ "$rule_logging" = "1" ] && {
$IPT -A mwan3_rules \
-p $proto \
${src_ip:+-s} $src_ip \
${src_dev:+-i} $src_dev \
${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
}
if [ "$family" == "any" ]; then
for IPT in "$IPT4" "$IPT6"; do
case $proto in
tcp|udp)
$IPT -A mwan3_rules -p $proto -s $src_ip -d $dest_ip $ipset -m multiport --sports $src_port -m multiport --dports $dest_port -m mark --mark 0/$MMX_MASK -m comment --comment "$1" -j $policy &> /dev/null
;;
*)
$IPT -A mwan3_rules -p $proto -s $src_ip -d $dest_ip $ipset -m mark --mark 0/$MMX_MASK -m comment --comment "$1" -j $policy &> /dev/null
;;
esac
done
elif [ "$family" == "ipv4" ]; then
case $proto in
tcp|udp)
$IPT4 -A mwan3_rules -p $proto -s $src_ip -d $dest_ip $ipset -m multiport --sports $src_port -m multiport --dports $dest_port -m mark --mark 0/$MMX_MASK -m comment --comment "$1" -j $policy &> /dev/null
;;
*)
$IPT4 -A mwan3_rules -p $proto -s $src_ip -d $dest_ip $ipset -m mark --mark 0/$MMX_MASK -m comment --comment "$1" -j $policy &> /dev/null
;;
esac
elif [ "$family" == "ipv6" ]; then
case $proto in
tcp|udp)
$IPT6 -A mwan3_rules -p $proto -s $src_ip -d $dest_ip $ipset -m multiport --sports $src_port -m multiport --dports $dest_port -m mark --mark 0/$MMX_MASK -m comment --comment "$1" -j $policy &> /dev/null
;;
*)
$IPT6 -A mwan3_rules -p $proto -s $src_ip -d $dest_ip $ipset -m mark --mark 0/$MMX_MASK -m comment --comment "$1" -j $policy &> /dev/null
;;
esac
fi
$IPT -A mwan3_rules \
-p $proto \
${src_ip:+-s} $src_ip \
${src_dev:+-i} $src_dev \
${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
done
fi
}
@ -798,7 +1045,7 @@ mwan3_set_iface_hotplug_state() {
mwan3_get_iface_hotplug_state() {
local iface=$1
cat $MWAN3_STATUS_DIR/iface_state/$iface 2>/dev/null || echo "unknown"
cat $MWAN3_STATUS_DIR/iface_state/$iface 2>/dev/null || echo "offline"
}
mwan3_report_iface_status()
@ -821,10 +1068,16 @@ mwan3_report_iface_status()
fi
if [ -z "$id" -o -z "$device" ]; then
result="unknown"
elif [ -n "$($IP rule | awk '$1 == "'$(($id+1000)):'"')" -a -n "$($IP rule | awk '$1 == "'$(($id+2000)):'"')" -a -n "$($IPT -S mwan3_iface_in_$1 2> /dev/null)" -a -n "$($IPT -S mwan3_iface_out_$1 2> /dev/null)" -a -n "$($IP route list table $id default dev $device 2> /dev/null)" ]; 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)"
elif [ -n "$($IP rule | awk '$1 == "'$(($id+1000)):'"')" -o -n "$($IP rule | awk '$1 == "'$(($id+2000)):'"')" -o -n "$($IPT -S mwan3_iface_in_$1 2> /dev/null)" -o -n "$($IPT -S mwan3_iface_out_$1 2> /dev/null)" -o -n "$($IP route list table $id default dev $device 2> /dev/null)" ]; then
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
result="offline"
@ -851,53 +1104,43 @@ mwan3_report_iface_status()
echo " interface $1 is $result and tracking is $tracking"
}
mwan3_report_policies()
{
local ipt="$1"
local policy="$2"
local percent total_weight weight iface
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}')
percent=$(($weight*100/$total_weight))
echo " $iface ($percent%)"
done
else
echo " $($ipt -S $policy | grep -v '.*--comment "out .*" .*$' | sed '/.*--comment \([^ ]*\) .*$/!d;s//\1/;q')"
fi
}
mwan3_report_policies_v4()
{
local percent policy share total_weight weight iface
local policy
for policy in $($IPT4 -S | awk '{print $2}' | grep mwan3_policy_ | sort -u); do
echo "$policy:" | sed 's/mwan3_policy_//'
[ -n "$total_weight" ] || total_weight=$($IPT4 -S $policy | cut -s -d'"' -f2 | head -1 | awk '{print $3}')
if [ ! -z "${total_weight##*[!0-9]*}" ]; then
for iface in $($IPT4 -S $policy | cut -s -d'"' -f2 | awk '{print $1}'); do
weight=$($IPT4 -S $policy | cut -s -d'"' -f2 | awk '$1 == "'$iface'"' | awk '{print $2}')
percent=$(($weight*100/$total_weight))
echo " $iface ($percent%)"
done
else
echo " $($IPT4 -S $policy | sed '/.*--comment \([^ ]*\) .*$/!d;s//\1/;q')"
fi
unset total_weight
echo -e
mwan3_report_policies "$IPT4" "$policy"
done
}
mwan3_report_policies_v6()
{
local percent policy share total_weight weight iface
local policy
for policy in $($IPT6 -S | awk '{print $2}' | grep mwan3_policy_ | sort -u); do
echo "$policy:" | sed 's/mwan3_policy_//'
[ -n "$total_weight" ] || total_weight=$($IPT6 -S $policy | cut -s -d'"' -f2 | head -1 | awk '{print $3}')
if [ ! -z "${total_weight##*[!0-9]*}" ]; then
for iface in $($IPT6 -S $policy | cut -s -d'"' -f2 | awk '{print $1}'); do
weight=$($IPT6 -S $policy | cut -s -d'"' -f2 | awk '$1 == "'$iface'"' | awk '{print $2}')
percent=$(($weight*100/$total_weight))
echo " $iface ($percent%)"
done
else
echo " $($IPT6 -S $policy | sed '/.*--comment \([^ ]*\) .*$/!d;s//\1/;q')"
fi
unset total_weight
echo -e
mwan3_report_policies "$IPT6" "$policy"
done
}
@ -906,9 +1149,7 @@ mwan3_report_connected_v4()
local address
if [ -n "$($IPT4 -S mwan3_connected 2> /dev/null)" ]; then
for address in $($IPS list mwan3_connected_v4 | egrep '[0-9]{1,3}(\.[0-9]{1,3}){3}'); do
echo " $address"
done
$IPS -o save list mwan3_connected_v4 | grep add | cut -d " " -f 3
fi
}
@ -917,9 +1158,7 @@ mwan3_report_connected_v6()
local address
if [ -n "$($IPT6 -S mwan3_connected 2> /dev/null)" ]; then
for address in $($IPS list mwan3_connected_v6 | egrep '([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])'); do
echo " $address"
done
$IPS -o save list mwan3_connected_v6 | grep add | cut -d " " -f 3
fi
}
@ -939,34 +1178,21 @@ mwan3_report_rules_v6()
mwan3_flush_conntrack()
{
local flush_conntrack
local interface="$1"
local action="$2"
config_get flush_conntrack $1 flush_conntrack never
handle_flush() {
local flush_conntrack="$1"
local action="$2"
if [ "$action" = "$flush_conntrack" ]; then
echo f > ${CONNTRACK_FILE}
$LOG info "Connection tracking flushed for interface '$interface' on action '$action'"
fi
}
if [ -e "$CONNTRACK_FILE" ]; then
case $flush_conntrack in
ifup)
[ "$3" = "ifup" ] && {
echo f > ${CONNTRACK_FILE}
$LOG info "connection tracking flushed on interface $1 ($2) $3"
}
;;
ifdown)
[ "$3" = "ifdown" ] && {
echo f > ${CONNTRACK_FILE}
$LOG info "connection tracking flushed on interface $1 ($2) $3"
}
;;
always)
echo f > ${CONNTRACK_FILE}
$LOG info "connection tracking flushed on interface $1 ($2) $3"
;;
never)
$LOG info "connection tracking not flushed on interface $1 ($2) $3"
;;
esac
else
$LOG warning "connection tracking not enabled"
config_list_foreach "$interface" flush_conntrack handle_flush "$action"
fi
}

View File

@ -15,7 +15,7 @@ report_connected_v4() {
local address
if [ -n "$($IPT4 -S mwan3_connected 2> /dev/null)" ]; then
for address in $($IPS list mwan3_connected_v4 | tail -n +8); do
for address in $($IPS -o save list mwan3_connected_v4 | grep add | cut -d " " -f 3); do
json_add_string "" "${address}"
done
fi
@ -25,18 +25,59 @@ report_connected_v6() {
local address
if [ -n "$($IPT6 -S mwan3_connected 2> /dev/null)" ]; then
for address in $($IPS list mwan3_connected_v6 | tail -n +8); do
for address in $($IPS -o save list mwan3_connected_v6 | grep add | cut -d " " -f 3); do
json_add_string "" "${address}"
done
fi
}
report_policies() {
local ipt="$1"
local policy="$2"
local percent total_weight weight iface
total_weight=$($ipt -S $policy | grep -v '.*--comment "out .*" .*$' | cut -s -d'"' -f2 | head -1 | awk '{print $3}')
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))
json_add_object
json_add_string interface "$iface"
json_add_int percent "$percent"
json_close_object
done
}
report_policies_v4() {
local policy
for policy in $($IPT4 -S | awk '{print $2}' | grep mwan3_policy_ | sort -u); do
json_add_array "${policy##*mwan3_policy_}"
report_policies "$IPT4" "$policy"
json_close_array
done
}
report_policies_v6() {
local policy
for policy in $($IPT6 -S | awk '{print $2}' | grep mwan3_policy_ | sort -u); do
json_add_array "${policy##*mwan3_policy_}"
report_policies "$IPT6" "$policy"
json_close_array
done
}
get_mwan3_status() {
local iface="${1}"
local iface_select="${2}"
local running="0"
local age=0
local pid device time_p time_n
local online=0
local offline=0
local up="0"
local enabled pid device time_p time_n time_u time_d status
network_get_device device $1
@ -52,13 +93,42 @@ get_mwan3_status() {
let age=time_n-time_p
}
time_u="$(cat "$MWAN3TRACK_STATUS_DIR/${iface}/ONLINE")"
[ -z "${time_u}" ] || [ "${time_u}" = "0" ] || {
time_n="$(get_uptime)"
let online=time_n-time_u
}
time_d="$(cat "$MWAN3TRACK_STATUS_DIR/${iface}/OFFLINE")"
[ -z "${time_d}" ] || [ "${time_d}" = "0" ] || {
time_n="$(get_uptime)"
let offline=time_n-time_d
}
local uptime="0"
config_get enabled "$iface" enabled 0
network_get_uptime uptime "$iface"
network_is_up "$iface" && up="1"
if [ -f "$MWAN3TRACK_STATUS_DIR/${iface}/STATUS" ]; then
status="$(cat "$MWAN3TRACK_STATUS_DIR/${iface}/STATUS")"
else
status="unknown"
fi
json_add_object "${iface}"
json_add_int age "$age"
json_add_int online "${online}"
json_add_int offline "${offline}"
json_add_int uptime "${uptime}"
json_add_int "score" "$(cat "$MWAN3TRACK_STATUS_DIR/${iface}/SCORE")"
json_add_int "lost" "$(cat "$MWAN3TRACK_STATUS_DIR/${iface}/LOST")"
json_add_int "turn" "$(cat "$MWAN3TRACK_STATUS_DIR/${iface}/TURN")"
json_add_string "status" "$(cat "$MWAN3TRACK_STATUS_DIR/${iface}/STATUS")"
json_add_string "status" "${status}"
json_add_boolean "enabled" "${enabled}"
json_add_boolean "running" "${running}"
json_add_boolean "up" "${up}"
json_add_array "track_ip"
for file in $MWAN3TRACK_STATUS_DIR/${iface}/*; do
track="${file#*/TRACK_}"
@ -84,6 +154,7 @@ main () {
json_add_object "status"
json_add_string "section" "x"
json_add_string "interface" "x"
json_add_string "policies" "x"
json_close_object
json_dump
;;
@ -114,6 +185,16 @@ main () {
json_close_array
json_close_object
;;
policies)
json_add_object policies
json_add_object ipv4
report_policies_v4
json_close_object
json_add_object ipv6
report_policies_v6
json_close_object
json_close_object
;;
*)
# interfaces
json_add_object interfaces
@ -128,6 +209,15 @@ main () {
report_connected_v6
json_close_array
json_close_object
# policies
json_add_object policies
json_add_object ipv4
report_policies_v4
json_close_object
json_add_object ipv6
report_policies_v6
json_close_object
json_close_object
;;
esac
json_dump

View File

@ -43,9 +43,15 @@ ifdown()
ifup()
{
local device enabled up l3_device
local device enabled up l3_device status
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."
exit 1
}
if [ -z "$1" ]; then
echo "Expecting interface. Usage: mwan3 ifup <interface>" && exit 0
@ -55,19 +61,17 @@ ifup()
echo "Too many arguments. Usage: mwan3 ifup <interface>" && exit 0
fi
config_get_bool enabled globals 'enabled' 0
[ ${enabled} -gt 0 ] || {
echo "Warning: mwan3 is global disabled. Usage: /etc/init.d/mwan3 start"
exit 0
status=$(ubus -S call network.interface.$1 status)
[ -n "$status" ] && {
json_load "$status"
json_get_vars up l3_device
}
json_load $(ubus -S call network.interface.$1 status)
json_get_vars up l3_device
config_get enabled "$1" enabled 0
if [ "$up" -eq 1 ] \
if [ "$up" = "1" ] \
&& [ -n "$l3_device" ] \
&& [ "$enabled" -eq 1 ]; then
&& [ "$enabled" = "1" ]; then
ACTION=ifup INTERFACE=$1 DEVICE=$l3_device /sbin/hotplug-call iface
fi
}
@ -121,39 +125,24 @@ status()
start()
{
local enabled src_ip local_source
local enabled
config_load mwan3
config_get_bool enabled globals 'enabled' 0
[ ${enabled} -gt 0 ] || {
echo "Warning: mwan3 is global disabled. Usage: /etc/init.d/mwan3 start"
exit 0
}
config_get local_source globals local_source 'none'
[ "${local_source}" = "none" ] || {
src_ip=$(uci_get_state mwan3 globals src_ip)
[ "${src_ip}" != "" ] && {
ip route del default via "${src_ip}" dev lo 1>/dev/null 2>&1
ip addr del "${src_ip}/32" dev lo 1>/dev/null 2>&1
}
network_get_ipaddr src_ip "${local_source}"
if [ "${src_ip}" = "" ]; then
$LOG warn "Unable to set source ip for own initiated traffic (${local_source})"
else
ip addr add "${src_ip}/32" dev lo
ip route add default via "${src_ip}" dev lo
uci_toggle_state mwan3 globals src_ip "${src_ip}"
fi
}
uci_toggle_state mwan3 globals enabled "1"
config_foreach ifup interface
}
stop()
{
local ipset route rule table IP IPT pid src_ip
local ipset route rule table IP IPT pid
mwan3_lock "command" "mwan3"
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
@ -197,14 +186,12 @@ stop()
$IPS -q destroy $ipset
done
mwan3_unlock "command" "mwan3"
mwan3_lock_clean
rm -rf $MWAN3_STATUS_DIR $MWAN3TRACK_STATUS_DIR
src_ip=$(uci_get_state mwan3 globals src_ip)
[ "${src_ip}" = "" ] || {
ip route del default via "${src_ip}" dev lo 1>/dev/null 2>&1
ip addr del "${src_ip}/32" dev lo 1>/dev/null 2>&1
}
uci_toggle_state mwan3 globals enabled "0"
}
restart() {

View File

@ -0,0 +1,38 @@
#!/bin/sh
. /lib/functions.sh
. /lib/mwan3/mwan3.sh
LOG="logger -t $(basename "$0")[$$] -p"
clean_up() {
$LOG notice "Stopping mwan3rtmon..."
exit 0
}
rtchange() {
$LOG info "Detect rtchange event."
}
main() {
local rtmon_interval
trap clean_up TERM
trap rtchange USR1
config_load mwan3
config_get rtmon_interval globals rtmon_interval '5'
sleep 3
while true; do
mwan3_lock "service" "mwan3rtmon"
mwan3_rtmon_ipv4 || mwan3_rtmon_ipv6
ret=$?
mwan3_unlock "service" "mwan3rtmon"
[ "$ret" = "0" ] || break
[ "$rtmon_interval" = "0" ] && break
sleep "$rtmon_interval" &
wait
done
}
main "$@"

View File

@ -6,6 +6,7 @@
LOG="logger -t $(basename "$0")[$$] -p"
INTERFACE=""
DEVICE=""
PING="/bin/ping"
IFDOWN_EVENT=0
@ -43,6 +44,12 @@ validate_track_method() {
return 1
}
;;
nping-*)
which nping 1>/dev/null 2>&1 || {
$LOG warn "Missing nping. Please install nping package."
return 1
}
;;
*)
$LOG warn "Unsupported tracking method: $track_method"
return 2
@ -55,6 +62,7 @@ main() {
local recovery_interval down up size
local keep_failure_interval check_quality failure_latency
local recovery_latency failure_loss recovery_loss
local max_ttl httping_ssl
[ -z "$5" ] && echo "Error: should not be started manually" && exit 0
@ -68,6 +76,7 @@ main() {
config_load mwan3
config_get track_method $1 track_method ping
config_get_bool httping_ssl $1 httping_ssl 0
validate_track_method $track_method $SRC_IP || {
track_method=ping
if validate_track_method $track_method; then
@ -84,6 +93,7 @@ main() {
config_get down $1 down 5
config_get up $1 up 5
config_get size $1 size 56
config_get max_ttl $1 max_ttl 60
config_get failure_interval $1 failure_interval $interval
config_get_bool keep_failure_interval $1 keep_failure_interval 0
config_get recovery_interval $1 recovery_interval $interval
@ -100,15 +110,22 @@ main() {
local sleep_time=0
local turn=0
local result
local ping_protocol=4
local ping_result
local ping_result_raw
local ping_status
local loss=0
local latency=0
if [ "$STATUS" = "unknown" ]; then
echo "unknown" > /var/run/mwan3track/$1/STATUS
if [ "$STATUS" = "offline" ]; then
echo "offline" > /var/run/mwan3track/$1/STATUS
echo "0" > /var/run/mwan3track/$1/ONLINE
echo "$(get_uptime)" > /var/run/mwan3track/$1/OFFLINE
score=0
else
echo "online" > /var/run/mwan3track/$1/STATUS
echo "0" > /var/run/mwan3track/$1/OFFLINE
echo "$(get_uptime)" > /var/run/mwan3track/$1/ONLINE
env -i ACTION="connected" INTERFACE="$1" DEVICE="$2" /sbin/hotplug-call iface
fi
while true; do
@ -119,14 +136,25 @@ main() {
if [ $host_up_count -lt $reliability ]; then
case "$track_method" in
ping)
# pinging IPv6 hosts with an interface is troublesome
# https://bugs.openwrt.org/index.php?do=details&task_id=2897
# so get the IP address of the interface and use that instead
if echo $track_ip | grep -q ':'; then
ADDR=$(ip -6 addr ls dev "$DEVICE" | sed -ne '/\/128/d' -e 's/ *inet6 \([^ \/]*\).* scope global.*/\1/p' | head -n1)
[ -z "$ADDR" ] && ADDR=$(ip -6 addr ls dev "$DEVICE" | sed -ne 's/ *inet6 \([^ \/]*\).* scope global.*/\1/p')
ping_protocol=6
fi
if [ $check_quality -eq 0 ]; then
ping -I $DEVICE -c $count -W $timeout -s $size -q $track_ip &> /dev/null
$PING -$ping_protocol -I ${ADDR:-$DEVICE} -c $count -W $timeout -s $size -t $max_ttl -q $track_ip &> /dev/null
result=$?
else
ping_result="$(ping -I $DEVICE -c $count -W $timeout -s $size -q $track_ip | tail -2)"
ping_result_raw="$($PING -$ping_protocol -I ${ADDR:-$DEVICE} -c $count -W $timeout -s $size -t $max_ttl -q $track_ip 2>/dev/null)"
ping_status=$?
ping_result=$(echo "$ping_result_raw" | tail -n2)
loss="$(echo "$ping_result" | grep "packet loss" | cut -d "," -f3 | awk '{print $1}' | sed -e 's/%//')"
if [ "$loss" -eq 100 ]; then
if [ "$ping_status" -ne 0 ] || [ "$loss" -eq 100 ]; then
latency=999999
loss=100
else
latency="$(echo "$ping_result" | grep -E 'rtt|round-trip' | cut -d "=" -f2 | cut -d "/" -f2 | cut -d "." -f1)"
fi
@ -137,9 +165,25 @@ main() {
result=$?
;;
httping)
httping -y $SRC_IP -c $count -t $timeout -q $track_ip &> /dev/null
if [ "$httping_ssl" -eq 1 ]; then
httping -y $SRC_IP -c $count -t $timeout -q "https://$track_ip" &> /dev/null
else
httping -y $SRC_IP -c $count -t $timeout -q "http://$track_ip" &> /dev/null
fi
result=$?
;;
nping-tcp)
result=$(nping -e $DEVICE -c $count $track_ip --tcp | grep Lost | awk '{print $12}')
;;
nping-udp)
result=$(nping -e $DEVICE -c $count $track_ip --udp | grep Lost | awk '{print $12}')
;;
nping-icmp)
result=$(nping -e $DEVICE -c $count $track_ip --icmp | grep Lost | awk '{print $12}')
;;
nping-arp)
result=$(nping -e $DEVICE -c $count $track_ip --arp | grep Lost | awk '{print $12}')
;;
esac
if [ $check_quality -eq 0 ]; then
if [ $result -eq 0 ]; then
@ -197,9 +241,7 @@ main() {
if [ $score -eq $up ]; then
echo "offline" > /var/run/mwan3track/$1/STATUS
$LOG notice "Interface $1 ($2) is offline"
env -i ACTION=ifdown INTERFACE=$1 DEVICE=$2 /sbin/hotplug-call iface
env -i ACTION="disconnected" INTERFACE="$1" DEVICE="$2" /sbin/hotplug-call iface
score=0
fi
else
@ -237,8 +279,12 @@ main() {
wait
if [ "${IFDOWN_EVENT}" -eq 1 ]; then
score=0
echo "offline" > /var/run/mwan3track/$1/STATUS
echo "$(get_uptime)" > /var/run/mwan3track/$1/OFFLINE
echo "0" > /var/run/mwan3track/$1/ONLINE
$LOG notice "Interface $1 ($2) is offline"
env -i ACTION="disconnected" INTERFACE="$1" DEVICE="$2" /sbin/hotplug-call iface
score=0
IFDOWN_EVENT=0
fi
done