Merge pull request #1992 from Adze1502/master

mwan3: update to version 2.0-0
This commit is contained in:
Steven Barth 2015-11-20 09:40:56 +01:00
commit 4cd52a64ac
6 changed files with 1019 additions and 603 deletions

View File

@ -8,8 +8,8 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=mwan3
PKG_VERSION:=1.6
PKG_RELEASE:=3
PKG_VERSION:=2.0
PKG_RELEASE:=0
PKG_MAINTAINER:=Jeroen Louwes <jeroen.louwes@gmail.com>
PKG_LICENSE:=GPLv2

View File

@ -1,21 +1,7 @@
config interface 'wan'
config interface 'wan1'
option enabled '1'
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 reliability '2'
option count '1'
option timeout '2'
option interval '5'
option down '3'
option up '8'
config interface 'wan2'
option enabled '0'
list track_ip '8.8.8.8'
list track_ip '208.67.220.220'
option reliability '1'
option count '1'
option timeout '2'
@ -23,58 +9,141 @@ config interface 'wan2'
option down '3'
option up '8'
config member 'wan_m1_w3'
option interface 'wan'
config interface 'wan2'
option enabled '1'
list track_ip '8.8.8.8'
option reliability '1'
option count '1'
option timeout '2'
option interval '5'
option down '3'
option up '8'
config interface 'wan3'
option enabled '1'
list track_ip '208.67.222.222'
option reliability '1'
option count '1'
option timeout '2'
option interval '5'
option down '3'
option up '8'
config interface 'wan1_v6'
option family 'ipv6'
option enabled '1'
list track_ip '2001:7b8:1::2'
option reliability '1'
option count '1'
option timeout '2'
option interval '5'
option down '3'
option up '8'
config interface 'wan2_v6'
option family 'ipv6'
option enabled '1'
list track_ip '2001:7b8:2::2'
option reliability '1'
option count '1'
option timeout '2'
option interval '5'
option down '3'
option up '8'
config interface 'wan3_v6'
option family 'ipv6'
option enabled '1'
list track_ip '2001:7b8:3::2'
option reliability '1'
option count '1'
option timeout '2'
option interval '5'
option down '3'
option up '8'
config member 'wan1_m1_w1'
option interface 'wan1'
option metric '1'
option weight '3'
option weight '1'
config member 'wan_m2_w3'
option interface 'wan'
option metric '2'
option weight '3'
config member 'wan2_m1_w2'
config member 'wan2_m1_w1'
option interface 'wan2'
option metric '1'
option weight '2'
option weight '1'
config member 'wan2_m2_w2'
option interface 'wan2'
option metric '2'
option weight '2'
config member 'wan3_m1_w1'
option interface 'wan3'
option metric '1'
option weight '1'
config policy 'wan_only'
list use_member 'wan_m1_w3'
config member 'wan1_v6_m1_w1'
option interface 'wan1_v6'
option metric '1'
option weight '1'
config member 'wan2_v6_m1_w1'
option interface 'wan2_v6'
option metric '1'
option weight '1'
config member 'wan3_v6_m1_w1'
option interface 'wan3_v6'
option metric '1'
option weight '1'
config policy 'wan1_only'
list use_member 'wan1_m1_w1'
config policy 'wan2_only'
list use_member 'wan2_m1_w2'
list use_member 'wan2_m1_w1'
config policy 'wan3_only'
list use_member 'wan3_m1_w1'
config policy 'wan1_v6_only'
list use_member 'wan1_v6_m1_w1'
config policy 'wan2_v6_only'
list use_member 'wan2_v6_m1_w1'
config policy 'wan3_v6_only'
list use_member 'wan3_v6_m1_w1'
config policy 'balanced'
list use_member 'wan_m1_w3'
list use_member 'wan2_m1_w2'
config policy 'wan_wan2'
list use_member 'wan_m1_w3'
list use_member 'wan2_m2_w2'
config policy 'wan2_wan'
list use_member 'wan_m2_w3'
list use_member 'wan2_m1_w2'
config rule 'youtube'
option sticky '1'
option ipset 'youtube'
option dest_port '80,443'
option proto 'tcp'
option use_policy 'balanced'
list use_member 'wan1_m1_w1'
list use_member 'wan2_m1_w1'
list use_member 'wan3_m1_w1'
list use_member 'wan1_v6_m1_w1'
list use_member 'wan2_v6_m1_w1'
list use_member 'wan3_v6_m1_w1'
config rule 'https'
option sticky '1'
option src_ip '2001:3::/64'
option dest_port '443'
option proto 'tcp'
option use_policy 'balanced'
config rule 'default_rule'
option dest_ip '0.0.0.0/0'
config rule 'https2'
option dest_port '19443'
option proto 'tcp'
option use_policy 'balanced'
option sticky '1'
config rule 'igs'
option proto 'icmp'
option family 'ipv4'
option sticky '1'
option ipset 'google'
option use_policy 'balanced'
config rule 'i6gs'
option proto 'icmpv6'
option family 'ipv6'
option sticky '1'
option ipset 'google'
option use_policy 'balanced'
config rule 'default_rule'
option use_policy 'balanced'

View File

@ -1,444 +1,49 @@
#!/bin/sh
local IP IPS IPT LOG
[ "$ACTION" == "ifup" -o "$ACTION" == "ifdown" ] || exit 1
[ -n "$INTERFACE" ] || exit 2
[ -n "$ACTION" ] || exit 0
[ -n "$INTERFACE" ] || exit 0
if [ $ACTION == "ifup" ]; then
[ -n "$DEVICE" ] || exit 0
if [ "$ACTION" == "ifup" ]; then
[ -n "$DEVICE" ] || exit 3
fi
if [ -x /usr/sbin/ip ]; then
IP="/usr/sbin/ip -4"
elif [ -x /usr/bin/ip ]; then
IP="/usr/bin/ip -4"
else
exit 1
fi
[ -x /usr/bin/ip ] || exit 4
[ -x /usr/sbin/ipset ] || exit 5
[ -x /usr/sbin/iptables ] || exit 6
[ -x /usr/sbin/ip6tables ] || exit 7
[ -x /usr/bin/logger ] || exit 8
if [ -x /usr/sbin/ipset ]; then
IPS="/usr/sbin/ipset"
else
exit 1
fi
. /lib/functions.sh
. /lib/functions/network.sh
. /lib/mwan3/mwan3.sh
if [ -x /usr/sbin/iptables ]; then
IPT="/usr/sbin/iptables -t mangle -w"
else
exit 1
fi
config_load mwan3
if [ -x /usr/bin/logger ]; then
LOG="/usr/bin/logger -t mwan3 -p"
else
exit 1
fi
config_get enabled $INTERFACE enabled 0
[ "$enabled" == "1" ] || exit 0
$LOG notice "$ACTION interface $INTERFACE (${DEVICE:-unknown})"
mwan3_get_iface_id()
{
let iface_count++
[ "$1" == "$INTERFACE" ] && iface_id=$iface_count
}
mwan3_set_general_iptables()
{
if ! $IPT -S mwan3_ifaces &> /dev/null; then
$IPT -N mwan3_ifaces
fi
if ! $IPT -S mwan3_connected &> /dev/null; then
$IPT -N mwan3_connected
$IPS create mwan3_connected hash:net
$IPT -A mwan3_connected -m set --match-set mwan3_connected dst -j MARK --set-xmark 0xff00/0xff00
fi
if ! $IPT -S mwan3_track &> /dev/null; then
$IPT -N mwan3_track
fi
if ! $IPT -S mwan3_rules &> /dev/null; then
$IPT -N mwan3_rules
fi
if ! $IPT -S mwan3_hook &> /dev/null; then
$IPT -N mwan3_hook
$IPT -A mwan3_hook -j CONNMARK --restore-mark --nfmask 0xff00 --ctmask 0xff00
$IPT -A mwan3_hook -m mark --mark 0x0/0xff00 -j mwan3_ifaces
$IPT -A mwan3_hook -m mark --mark 0x0/0xff00 -j mwan3_connected
$IPT -A mwan3_hook -m mark --mark 0x0/0xff00 -j mwan3_track
$IPT -A mwan3_hook -m mark --mark 0x0/0xff00 -j mwan3_rules
$IPT -A mwan3_hook -j CONNMARK --save-mark --nfmask 0xff00 --ctmask 0xff00
$IPT -A mwan3_hook -m mark ! --mark 0xff00/0xff00 -j mwan3_connected
fi
if ! $IPT -S PREROUTING | grep mwan3_hook &> /dev/null; then
$IPT -A PREROUTING -j mwan3_hook
fi
if ! $IPT -S OUTPUT | grep mwan3_hook &> /dev/null; then
$IPT -A OUTPUT -j mwan3_hook
fi
$IPT -F mwan3_rules
}
mwan3_set_general_rules()
{
if [ -z "$($IP rule list | awk '$1 == "2253:"')" ]; then
$IP rule add pref 2253 fwmark 0xfd00/0xff00 blackhole
fi
if [ -z "$($IP rule list | awk '$1 == "2254:"')" ]; then
$IP rule add pref 2254 fwmark 0xfe00/0xff00 unreachable
fi
}
mwan3_set_connected_iptables()
{
local connected_network
if $IPT -S mwan3_connected &> /dev/null; then
$IPS create mwan3_connected_temp hash:net
for connected_network in $($IP route | awk '{print $1}' | egrep '[0-9]{1,3}(\.[0-9]{1,3}){3}'); do
$IPS -! add mwan3_connected_temp $connected_network
done
for connected_network in $($IP route list table 0 | awk '{print $2}' | egrep '[0-9]{1,3}(\.[0-9]{1,3}){3}'); do
$IPS -! add mwan3_connected_temp $connected_network
done
$IPS add mwan3_connected_temp 224.0.0.0/3
$IPS swap mwan3_connected_temp mwan3_connected
$IPS destroy mwan3_connected_temp
fi
}
mwan3_set_iface_iptables()
{
if ! $IPT -S mwan3_iface_$INTERFACE &> /dev/null; then
$IPT -N mwan3_iface_$INTERFACE
fi
$IPT -F mwan3_iface_$INTERFACE
$IPT -D mwan3_ifaces -m mark --mark 0x0/0xff00 -j mwan3_iface_$INTERFACE &> /dev/null
if [ $ACTION == "ifup" ]; then
$IPT -I mwan3_iface_$INTERFACE -i $DEVICE -m set --match-set mwan3_connected src -m mark --mark 0x0/0xff00 -m comment --comment "default" -j MARK --set-xmark 0xff00/0xff00
$IPT -A mwan3_iface_$INTERFACE -i $DEVICE -m mark --mark 0x0/0xff00 -m comment --comment "$INTERFACE" -j MARK --set-xmark $(($iface_id*256))/0xff00
$IPT -A mwan3_ifaces -m mark --mark 0x0/0xff00 -j mwan3_iface_$INTERFACE
fi
if [ $ACTION == "ifdown" ]; then
$IPT -X mwan3_iface_$INTERFACE
fi
}
mwan3_set_iface_route()
{
$IP route flush table $iface_id
[ $ACTION == "ifup" ] && $IP route add table $iface_id default $route_args
}
mwan3_set_iface_rules()
{
while [ -n "$($IP rule list | awk '$1 == "'$(($iface_id+1000)):'"')" ]; do
$IP rule del pref $(($iface_id+1000))
done
while [ -n "$($IP rule list | awk '$1 == "'$(($iface_id+2000)):'"')" ]; do
$IP rule del pref $(($iface_id+2000))
done
[ $ACTION == "ifup" ] && $IP rule add pref $(($iface_id+1000)) iif $DEVICE lookup main
[ $ACTION == "ifup" ] && $IP rule add pref $(($iface_id+2000)) fwmark $(($iface_id*256))/0xff00 lookup $iface_id
}
mwan3_set_iface_ipset()
{
local setname entry
for setname in $(ipset -n list | grep ^mwan3_sticky_); do
for entry in $(ipset list $setname | grep "$(echo $(($iface_id*256)) | awk '{ printf "0x%08x", $1; }')" | cut -d ' ' -f 1); do
$IPS del $setname $entry
done
done
}
mwan3_track()
{
local track_ip track_ips reliability count timeout interval down up
mwan3_list_track_ips()
{
track_ips="$1 $track_ips"
}
config_list_foreach $INTERFACE track_ip mwan3_list_track_ips
if [ -e /var/run/mwan3track-$INTERFACE.pid ] ; then
kill $(cat /var/run/mwan3track-$INTERFACE.pid) &> /dev/null
rm /var/run/mwan3track-$INTERFACE.pid &> /dev/null
fi
if [ -n "$track_ips" ]; then
config_get reliability $INTERFACE reliability 1
config_get count $INTERFACE count 1
config_get timeout $INTERFACE timeout 4
config_get interval $INTERFACE interval 10
config_get down $INTERFACE down 5
config_get up $INTERFACE up 5
$IPS -! create mwan3_track_$INTERFACE hash:ip
$IPS create mwan3_track_temp_$INTERFACE hash:ip
for track_ip in $track_ips; do
$IPS -! add mwan3_track_temp_$INTERFACE $track_ip
done
$IPS swap mwan3_track_temp_$INTERFACE mwan3_track_$INTERFACE
$IPS destroy mwan3_track_temp_$INTERFACE
$IPT -D mwan3_track -p icmp -m set --match-set mwan3_track_$INTERFACE dst -m icmp --icmp-type 8 -m length --length 32 -j MARK --set-xmark 0xff00/0xff00 &> /dev/null
$IPT -A mwan3_track -p icmp -m set --match-set mwan3_track_$INTERFACE dst -m icmp --icmp-type 8 -m length --length 32 -j MARK --set-xmark 0xff00/0xff00
[ -x /usr/sbin/mwan3track ] && /usr/sbin/mwan3track $INTERFACE $DEVICE $reliability $count $timeout $interval $down $up $track_ips &
else
$IPT -D mwan3_track -p icmp -m set --match-set mwan3_track_$INTERFACE dst -m icmp --icmp-type 8 -m length --length 32 -j MARK --set-xmark 0xff00/0xff00 &> /dev/null
$IPS destroy mwan3_track_$INTERFACE
fi
}
mwan3_set_policy()
{
local iface_count iface_id INTERFACE metric probability weight
config_get INTERFACE $1 interface
config_get metric $1 metric 1
config_get weight $1 weight 1
[ -n "$INTERFACE" ] || return 0
config_foreach mwan3_get_iface_id interface
[ -n "$iface_id" ] || return 0
if $IPT -S mwan3_iface_$INTERFACE &> /dev/null; then
if [ "$metric" -lt "$lowest_metric" ]; then
total_weight=$weight
$IPT -F mwan3_policy_$policy
$IPT -A mwan3_policy_$policy -m mark --mark 0x0/0xff00 -m comment --comment "$INTERFACE $weight $weight" -j MARK --set-xmark $(($iface_id*256))/0xff00
lowest_metric=$metric
elif [ "$metric" -eq "$lowest_metric" ]; then
total_weight=$(($total_weight+$weight))
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
probability="-m statistic --mode random --probability $probability"
$IPT -I mwan3_policy_$policy -m mark --mark 0x0/0xff00 $probability -m comment --comment "$INTERFACE $weight $total_weight" -j MARK --set-xmark $(($iface_id*256))/0xff00
fi
fi
}
mwan3_set_policies_iptables()
{
local last_resort lowest_metric policy total_weight
policy=$1
config_get last_resort $1 last_resort unreachable
if [ "$policy" != $(echo "$policy" | cut -c1-15) ]; then
$LOG warn "Policy $policy exceeds max of 15 chars. Not setting policy" && return 0
fi
if ! $IPT -S mwan3_policy_$policy &> /dev/null; then
$IPT -N mwan3_policy_$policy
fi
$IPT -F mwan3_policy_$policy
case "$last_resort" in
blackhole)
$IPT -A mwan3_policy_$policy -m mark --mark 0x0/0xff00 -m comment --comment "blackhole" -j MARK --set-xmark 0xfd00/0xff00
;;
default)
$IPT -A mwan3_policy_$policy -m mark --mark 0x0/0xff00 -m comment --comment "default" -j MARK --set-xmark 0xff00/0xff00
;;
*)
$IPT -A mwan3_policy_$policy -m mark --mark 0x0/0xff00 -m comment --comment "unreachable" -j MARK --set-xmark 0xfe00/0xff00
;;
esac
lowest_metric=256
total_weight=0
config_list_foreach $policy use_member mwan3_set_policy
}
mwan3_set_sticky_iptables()
{
local INTERFACE iface_count iface_id
INTERFACE="$1"
config_foreach mwan3_get_iface_id interface
unset iface_count
$IPS -! create mwan3_sticky_$rule hash:ip,mark markmask 0xff00 timeout $timeout
if [ -n "$iface_id" ]; then
if [ -n "$($IPT -S mwan3_iface_$1 2> /dev/null)" ]; then
$IPT -I mwan3_rule_$rule -m set ! --match-set mwan3_sticky_$rule src,src -j MARK --set-xmark 0x0/0xff00
$IPT -I mwan3_rule_$rule -m mark --mark 0/0xff00 -j MARK --set-xmark $(($iface_id*256))/0xff00
fi
fi
unset iface_id
}
mwan3_set_user_rules_iptables()
{
local ipset proto src_ip src_port sticky dest_ip dest_port use_policy rule timeout
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 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 use_policy $1 use_policy
rule="$1"
if [ "$rule" != $(echo "$rule" | cut -c1-15) ]; then
$LOG warn "Rule $rule exceeds max of 15 chars. Not setting rule" && return 0
fi
if [ -n "$ipset" ]; then
if [ -z "$($IPS -n list $ipset)" ]; then
$IPS create $ipset hash:ip timeout 3600
fi
ipset="-m set --match-set $ipset dst"
fi
if [ -n "$use_policy" ]; then
if [ "$use_policy" == "default" ]; then
use_policy="MARK --set-xmark 0xff00/0xff00"
elif [ "$use_policy" == "unreachable" ]; then
use_policy="MARK --set-xmark 0xfe00/0xff00"
elif [ "$use_policy" == "blackhole" ]; then
use_policy="MARK --set-xmark 0xfd00/0xff00"
else
if [ "$sticky" -eq 1 ]; then
if ! $IPT -S mwan3_rule_$rule &> /dev/null; then
$IPT -N mwan3_rule_$rule
fi
$IPT -F mwan3_rule_$rule
config_foreach mwan3_set_sticky_iptables interface
$IPT -A mwan3_rule_$rule -m mark --mark 0/0xff00 -j mwan3_policy_$use_policy
$IPT -A mwan3_rule_$rule -m mark ! --mark 0xfc00/0xfc00 -j SET --del-set mwan3_sticky_$rule src,src
$IPT -A mwan3_rule_$rule -m mark ! --mark 0xfc00/0xfc00 -j SET --add-set mwan3_sticky_$rule src,src
use_policy="mwan3_rule_$rule"
else
use_policy="mwan3_policy_$use_policy"
fi
fi
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/0xff00 -m comment --comment "$1" -j $use_policy &> /dev/null
;;
*)
$IPT -A mwan3_rules -p $proto -s $src_ip -d $dest_ip $ipset -m mark --mark 0/0xff00 -m comment --comment "$1" -j $use_policy &> /dev/null
;;
esac
fi
}
mwan3_ifupdown()
{
local counter enabled iface_count iface_id route_args wan_metric
config_load mwan3
config_foreach mwan3_get_iface_id interface
[ -n "$iface_id" ] || return 0
[ "$iface_count" -le 250 ] || return 0
unset iface_count
config_get enabled $INTERFACE enabled 0
counter=0
if [ $ACTION == "ifup" ]; then
[ "$enabled" -eq 1 ] || return 0
while [ -z "$($IP route list dev $DEVICE default | head -1)" -a "$counter" -lt 10 ]; do
sleep 1
let counter++
if [ "$counter" -ge 10 ]; then
$LOG warn "Could not find gateway for interface $INTERFACE ($DEVICE)" && return 0
fi
done
route_args=$($IP route list dev $DEVICE default | head -1 | sed '/.*via \([^ ]*\) .*$/!d;s//via \1/;q' | egrep '[0-9]{1,3}(\.[0-9]{1,3}){3}')
route_args="$route_args dev $DEVICE"
fi
while [ "$(pgrep -f -o hotplug-call)" -ne $$ -a "$counter" -lt 60 ]; do
sleep 1
let counter++
if [ "$counter" -ge 60 ]; then
$LOG warn "Timeout waiting for older hotplug processes to finish. $ACTION interface $INTERFACE (${DEVICE:-unknown}) aborted" && return 0
fi
done
$LOG notice "$ACTION interface $INTERFACE (${DEVICE:-unknown})"
mwan3_set_general_iptables
mwan3_set_general_rules
mwan3_set_iface_iptables
mwan3_set_iface_route
mwan3_set_iface_rules
[ $ACTION == "ifdown" ] && mwan3_set_iface_ipset
[ $ACTION == "ifup" ] && mwan3_track
config_foreach mwan3_set_policies_iptables policy
config_foreach mwan3_set_user_rules_iptables rule
}
mwan3_set_connected_iptables
case "$ACTION" in
ifup|ifdown)
mwan3_ifupdown
mwan3_set_connected_iptables
ifup)
mwan3_set_general_rules
mwan3_set_general_iptables
mwan3_create_iface_rules $INTERFACE $DEVICE
mwan3_create_iface_iptables $INTERFACE $DEVICE
mwan3_create_iface_route $INTERFACE $DEVICE
mwan3_track $INTERFACE $DEVICE
mwan3_set_user_rules
;;
ifdown)
mwan3_delete_iface_rules $INTERFACE
mwan3_delete_iface_iptables $INTERFACE
mwan3_delete_iface_route $INTERFACE
mwan3_delete_iface_ipset_entries $INTERFACE
;;
esac
config_foreach mwan3_create_policies_iptables policy
exit 0

View File

@ -0,0 +1,803 @@
#!/bin/sh
local IP4 IP6 IPS IPT4 IPT6 LOG
IP4="/usr/bin/ip -4"
IP6="/usr/bin/ip -6"
IPS="/usr/sbin/ipset"
IPT4="/usr/sbin/iptables -t mangle -w"
IPT6="/usr/sbin/ip6tables -t mangle -w"
LOG="/usr/bin/logger -t mwan3 -p"
mwan3_get_iface_id()
{
local _tmp _iface _iface_count
_iface="$2"
mwan3_get_id()
{
let _iface_count++
[ "$1" == "$_iface" ] && _tmp=$_iface_count
}
config_foreach mwan3_get_id interface
export "$1=$_tmp"
}
mwan3_set_connected_iptables()
{
local connected_network_v4 connected_network_v6
$IPS -! create mwan3_connected_v4 hash:net
$IPS create mwan3_connected_v4_temp hash:net
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
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
done
$IPS add mwan3_connected_v4_temp 224.0.0.0/3
$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 '([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
$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_connected list:set
$IPS -! add mwan3_connected mwan3_connected_v4
$IPS -! add mwan3_connected mwan3_connected_v6
}
mwan3_set_general_rules()
{
local IP
for IP in "$IP4" "$IP6"; do
if [ -z "$($IP rule list | awk '$1 == "2253:"')" ]; then
$IP rule add pref 2253 fwmark 0xfd00/0xff00 blackhole
fi
if [ -z "$($IP rule list | awk '$1 == "2254:"')" ]; then
$IP rule add pref 2254 fwmark 0xfe00/0xff00 unreachable
fi
done
}
mwan3_set_general_iptables()
{
local IPT
for IPT in "$IPT4" "$IPT6"; do
if ! $IPT -S mwan3_ifaces_in &> /dev/null; then
$IPT -N mwan3_ifaces_in
fi
if ! $IPT -S mwan3_ifaces_out &> /dev/null; then
$IPT -N mwan3_ifaces_out
fi
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 0xff00/0xff00
fi
if ! $IPT -S mwan3_rules &> /dev/null; then
$IPT -N mwan3_rules
fi
if ! $IPT -S mwan3_hook &> /dev/null; then
$IPT -N mwan3_hook
$IPT -A mwan3_hook -j CONNMARK --restore-mark --nfmask 0xff00 --ctmask 0xff00
$IPT -A mwan3_hook -m mark --mark 0x0/0xff00 -j mwan3_ifaces_in
$IPT -A mwan3_hook -m mark --mark 0x0/0xff00 -j mwan3_ifaces_out
$IPT -A mwan3_hook -m mark --mark 0x0/0xff00 -j mwan3_connected
$IPT -A mwan3_hook -m mark --mark 0x0/0xff00 -j mwan3_rules
$IPT -A mwan3_hook -j CONNMARK --save-mark --nfmask 0xff00 --ctmask 0xff00
$IPT -A mwan3_hook -m mark ! --mark 0xff00/0xff00 -j mwan3_connected
fi
if ! $IPT -S PREROUTING | grep mwan3_hook &> /dev/null; then
$IPT -A PREROUTING -j mwan3_hook
fi
if ! $IPT -S OUTPUT | grep mwan3_hook &> /dev/null; then
$IPT -A OUTPUT -j mwan3_hook
fi
done
}
mwan3_create_iface_iptables()
{
local id family src_ip src_ipv6
config_get family $1 family ipv4
mwan3_get_iface_id id $1
[ -n "$id" ] || return 0
if [ "$family" == "ipv4" ]; then
network_get_ipaddr src_ip $1
$IPS -! create mwan3_connected list:set
if ! $IPT4 -S mwan3_ifaces_in &> /dev/null; then
$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/0xff00 -m comment --comment "default" -j MARK --set-xmark 0xff00/0xff00
$IPT4 -A mwan3_iface_in_$1 -i $2 -m mark --mark 0x0/0xff00 -m comment --comment "$1" -j MARK --set-xmark $(($id*256))/0xff00
$IPT4 -D mwan3_ifaces_in -m mark --mark 0x0/0xff00 -j mwan3_iface_in_$1 &> /dev/null
$IPT4 -A mwan3_ifaces_in -m mark --mark 0x0/0xff00 -j mwan3_iface_in_$1
$IPT4 -F mwan3_iface_out_$1
$IPT4 -A mwan3_iface_out_$1 -s $src_ip -m mark --mark 0x0/0xff00 -m comment --comment "$1" -j MARK --set-xmark $(($id*256))/0xff00
$IPT4 -D mwan3_ifaces_out -m mark --mark 0x0/0xff00 -j mwan3_iface_out_$1 &> /dev/null
$IPT4 -A mwan3_ifaces_out -m mark --mark 0x0/0xff00 -j mwan3_iface_out_$1
fi
if [ "$family" == "ipv6" ]; then
network_get_ipaddr6 src_ipv6 $1
$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_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/0xff00 -m comment --comment "default" -j MARK --set-xmark 0xff00/0xff00
$IPT6 -A mwan3_iface_in_$1 -i $2 -m mark --mark 0x0/0xff00 -m comment --comment "$1" -j MARK --set-xmark $(($id*256))/0xff00
$IPT6 -D mwan3_ifaces_in -m mark --mark 0x0/0xff00 -j mwan3_iface_in_$1 &> /dev/null
$IPT6 -A mwan3_ifaces_in -m mark --mark 0x0/0xff00 -j mwan3_iface_in_$1
$IPT6 -F mwan3_iface_out_$1
$IPT6 -A mwan3_iface_out_$1 -s $src_ipv6 -m mark --mark 0x0/0xff00 -m comment --comment "$1" -j MARK --set-xmark $(($id*256))/0xff00
$IPT6 -D mwan3_ifaces_out -m mark --mark 0x0/0xff00 -j mwan3_iface_out_$1 &> /dev/null
$IPT6 -A mwan3_ifaces_out -m mark --mark 0x0/0xff00 -j mwan3_iface_out_$1
fi
}
mwan3_delete_iface_iptables()
{
config_get family $1 family ipv4
if [ "$family" == "ipv4" ]; then
$IPT4 -D mwan3_ifaces_in -m mark --mark 0x0/0xff00 -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/0xff00 -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/0xff00 -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/0xff00 -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
config_get family $1 family ipv4
mwan3_get_iface_id id $1
[ -n "$id" ] || return 0
if [ "$family" == "ipv4" ]; then
network_get_gateway route_args $1
route_args="via $route_args dev $2"
$IP4 route flush table $id
$IP4 route add table $id default $route_args
fi
if [ "$family" == "ipv6" ]; then
network_get_gateway6 route_args $1
route_args="via $route_args dev $2"
$IP6 route flush table $id
$IP6 route add table $id default $route_args
fi
}
mwan3_delete_iface_route()
{
local id
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
fi
if [ "$family" == "ipv6" ]; then
$IP6 route flush table $id
fi
}
mwan3_create_iface_rules()
{
local id family
config_get family $1 family ipv4
mwan3_get_iface_id id $1
[ -n "$id" ] || return 0
if [ "$family" == "ipv4" ]; then
while [ -n "$($IP4 rule list | awk '$1 == "'$(($id+1000)):'"')" ]; do
$IP4 rule del pref $(($id+1000))
done
while [ -n "$($IP4 rule list | awk '$1 == "'$(($id+2000)):'"')" ]; do
$IP4 rule del pref $(($id+2000))
done
$IP4 rule add pref $(($id+1000)) iif $2 lookup main
$IP4 rule add pref $(($id+2000)) fwmark $(($id*256))/0xff00 lookup $id
fi
if [ "$family" == "ipv6" ]; then
while [ -n "$($IP6 rule list | awk '$1 == "'$(($id+1000)):'"')" ]; do
$IP6 rule del pref $(($id+1000))
done
while [ -n "$($IP6 rule list | awk '$1 == "'$(($id+2000)):'"')" ]; do
$IP6 rule del pref $(($id+2000))
done
$IP6 rule add pref $(($id+1000)) iif $2 lookup main
$IP6 rule add pref $(($id+2000)) fwmark $(($id*256))/0xff00 lookup $id
fi
}
mwan3_delete_iface_rules()
{
local id family
config_get family $1 family ipv4
mwan3_get_iface_id id $1
[ -n "$id" ] || return 0
if [ "$family" == "ipv4" ]; then
while [ -n "$($IP4 rule list | awk '$1 == "'$(($id+1000)):'"')" ]; do
$IP4 rule del pref $(($id+1000))
done
while [ -n "$($IP4 rule list | awk '$1 == "'$(($id+2000)):'"')" ]; do
$IP4 rule del pref $(($id+2000))
done
fi
if [ "$family" == "ipv6" ]; then
while [ -n "$($IP6 rule list | awk '$1 == "'$(($id+1000)):'"')" ]; do
$IP6 rule del pref $(($id+1000))
done
while [ -n "$($IP6 rule list | awk '$1 == "'$(($id+2000)):'"')" ]; do
$IP6 rule del pref $(($id+2000))
done
fi
}
mwan3_delete_iface_ipset_entries()
{
local id setname entry
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 $(($id*256)) | awk '{ printf "0x%08x", $1; }')" | cut -d ' ' -f 1); do
$IPS del $setname $entry
done
done
}
mwan3_track()
{
local track_ip track_ips reliability count timeout interval down up
mwan3_list_track_ips()
{
track_ips="$1 $track_ips"
}
config_list_foreach $1 track_ip mwan3_list_track_ips
if [ -e /var/run/mwan3track-$1.pid ] ; then
kill $(cat /var/run/mwan3track-$1.pid) &> /dev/null
rm /var/run/mwan3track-$1.pid &> /dev/null
fi
if [ -n "$track_ips" ]; then
config_get reliability $1 reliability 1
config_get count $1 count 1
config_get timeout $1 timeout 4
config_get interval $1 interval 10
config_get down $1 down 5
config_get up $1 up 5
[ -x /usr/sbin/mwan3track ] && /usr/sbin/mwan3track $1 $2 $reliability $count $timeout $interval $down $up $track_ips &
fi
}
mwan3_set_policy()
{
local iface_count id iface family metric probability weight
config_get iface $1 interface
config_get metric $1 metric 1
config_get weight $1 weight 1
[ -n "$iface" ] || return 0
mwan3_get_iface_id id $iface
[ -n "$id" ] || return 0
config_get family $iface family ipv4
if [ "$family" == "ipv4" ]; then
if [ -n "$($IP4 route list table $id)" ]; 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/0xff00 -m comment --comment "$iface $weight $weight" -j MARK --set-xmark $(($id*256))/0xff00
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/0xff00 $probability -m comment --comment "$iface $weight $total_weight_v4" -j MARK --set-xmark $(($id*256))/0xff00
fi
fi
fi
if [ "$family" == "ipv6" ]; then
if [ -n "$($IP6 route list table $id)" ]; 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/0xff00 -m comment --comment "$iface $weight $weight" -j MARK --set-xmark $(($id*256))/0xff00
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/0xff00 $probability -m comment --comment "$iface $weight $total_weight_v6" -j MARK --set-xmark $(($id*256))/0xff00
fi
fi
fi
}
mwan3_create_policies_iptables()
{
local last_resort lowest_metric_v4 lowest_metric_v6 total_weight_v4 total_weight_v6 policy IPT
policy="$1"
config_get last_resort $1 last_resort unreachable
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
fi
$IPT -F mwan3_policy_$1
case "$last_resort" in
blackhole)
$IPT -A mwan3_policy_$1 -m mark --mark 0x0/0xff00 -m comment --comment "blackhole" -j MARK --set-xmark 0xfd00/0xff00
;;
default)
$IPT -A mwan3_policy_$1 -m mark --mark 0x0/0xff00 -m comment --comment "default" -j MARK --set-xmark 0xff00/0xff00
;;
*)
$IPT -A mwan3_policy_$1 -m mark --mark 0x0/0xff00 -m comment --comment "unreachable" -j MARK --set-xmark 0xfe00/0xff00
;;
esac
done
lowest_metric_v4=256
total_weight_v4=0
lowest_metric_v6=256
total_weight_v6=0
config_list_foreach $1 use_member mwan3_set_policy
}
mwan3_set_sticky_iptables()
{
local id
mwan3_get_iface_id id $1
[ -n "$id" ] || return 0
$IPS -! create mwan3_sticky_v4_$rule hash:ip,mark markmask 0xff00 timeout $timeout
$IPS -! create mwan3_sticky_v6_$rule hash:ip,mark markmask 0xff00 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
for IPT in "$IPT4" "$IPT6"; do
if [ -n "$($IPT -S mwan3_iface_$1 2> /dev/null)" ]; then
$IPT -I mwan3_rule_$rule -m set ! --match-set mwan3_sticky_$rule src,src -j MARK --set-xmark 0x0/0xff00
$IPT -I mwan3_rule_$rule -m mark --mark 0/0xff00 -j MARK --set-xmark $(($id*256))/0xff00
fi
done
}
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
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 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 use_policy $1 use_policy
config_get family $1 family any
if [ "$1" != $(echo "$1" | cut -c1-15) ]; then
$LOG warn "Rule $1 exceeds max of 15 chars. Not setting rule" && return 0
fi
if [ -n "$ipset" ]; then
if [ -z "$($IPS -n list $ipset 2> /dev/null)" ]; then
$IPS create $ipset list:set
$IPS create v4_$ipset hash:ip timeout 3600
$IPS create v6_$ipset hash:ip timeout 3600 family inet6
$IPS add $ipset v4_$ipset
$IPS add $ipset v6_$ipset
fi
ipset="-m set --match-set $ipset dst"
fi
if [ -n "$use_policy" ]; then
if [ "$use_policy" == "default" ]; then
policy="MARK --set-xmark 0xff00/0xff00"
elif [ "$use_policy" == "unreachable" ]; then
policy="MARK --set-xmark 0xfe00/0xff00"
elif [ "$use_policy" == "blackhole" ]; then
policy="MARK --set-xmark 0xfd00/0xff00"
else
if [ "$sticky" -eq 1 ]; then
policy="mwan3_policy_$use_policy"
config_foreach mwan3_set_sticky_iptables interface
for IPT in "$IPT4" "$IPT6"; do
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
fi
$IPT -F mwan3_rule_$1
$IPT -A mwan3_rule_$1 -m mark --mark 0/0xff00 -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"
else
policy="mwan3_policy_$use_policy"
for IPT in "$IPT4" "$IPT6"; do
if ! $IPT -S $policy &> /dev/null; then
$IPT -N $policy
fi
done
fi
fi
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/0xff00 -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/0xff00 -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/0xff00 -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/0xff00 -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/0xff00 -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/0xff00 -m comment --comment "$1" -j $policy &> /dev/null
;;
esac
fi
fi
}
mwan3_set_user_rules()
{
local IPT
for IPT in "$IPT4" "$IPT6"; do
if ! $IPT -S mwan3_rules &> /dev/null; then
$IPT -N mwan3_rules
fi
$IPT -F mwan3_rules
done
config_foreach mwan3_set_user_iptables_rule rule
}
mwan3_report_iface_status()
{
local device result track_ips tracking IP IPT
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
IP="$IP4"
IPT="$IPT4"
fi
if [ "$family" == "ipv6" ]; then
IP="$IP6"
IPT="$IPT6"
fi
if [ -z "$id" -o -z "$device" ]; then
result="unknown"
elif [ -n "$($IP rule | awk '$1 == "'$(($id+1000)):'"')"i -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="online"
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
result="error"
else
if [ "$enabled" == "1" ]; then
result="offline"
else
result="disabled"
fi
fi
mwan3_list_track_ips()
{
track_ips="$1 $track_ips"
}
config_list_foreach $1 track_ip mwan3_list_track_ips
if [ -n "$track_ips" ]; then
if [ -n "$(ps -w | grep mwan3track | grep -v grep | sed '/.*\/usr\/sbin\/mwan3track \([^ ]*\) .*$/!d;s//\1/' | awk '$1 == "'$1'"')" ]; then
tracking="active"
else
tracking="down"
fi
else
tracking="not enabled"
fi
echo " interface $1 is $result and tracking is $tracking"
}
mwan3_report_policies_v4()
{
local percent policy share total_weight weight iface
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
done
}
mwan3_report_policies_v6()
{
local percent policy share total_weight weight iface
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
done
}
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
fi
}
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
fi
}
mwan3_report_rules_v4()
{
if [ -n "$($IPT4 -S mwan3_rules 2> /dev/null)" ]; then
$IPT4 -L mwan3_rules -n -v 2> /dev/null | tail -n+3 | sed 's/mark.*//' | sed 's/mwan3_policy_/- /' | sed 's/mwan3_rule_/S /'
fi
}
mwan3_report_rules_v6()
{
if [ -n "$($IPT6 -S mwan3_rules 2> /dev/null)" ]; then
$IPT6 -L mwan3_rules -n -v 2> /dev/null | tail -n+3 | sed 's/mark.*//' | sed 's/mwan3_policy_/- /' | sed 's/mwan3_rule_/S /'
fi
}

View File

@ -1,26 +1,14 @@
#!/bin/sh
if [ -x /usr/sbin/ip ]; then
IP="/usr/sbin/ip -4"
elif [ -x /usr/bin/ip ]; then
IP="/usr/bin/ip -4"
else
exit 1
fi
if [ -x /usr/sbin/ipset ]; then
IPS="/usr/sbin/ipset"
else
exit 1
fi
if [ -x /usr/sbin/iptables ]; then
IPT="/usr/sbin/iptables -t mangle -w"
else
exit 1
fi
[ -x /usr/bin/ip ] || exit 4
[ -x /usr/sbin/ipset ] || exit 5
[ -x /usr/sbin/iptables ] || exit 6
[ -x /usr/sbin/ip6tables ] || exit 7
[ -x /usr/bin/logger ] || exit 8
. /lib/functions.sh
. /lib/functions/network.sh
. /lib/mwan3/mwan3.sh
help()
{
@ -34,8 +22,9 @@ Available commands:
ifup <iface> Load rules and routes for specific interface
ifdown <iface> Unload rules and routes for specific interface
interfaces Show interfaces status
policies Show policies status
rules Show rules status
policies Show currently active policy
connected Show directly connected networks
rules Show active rules
status Show all status
EOF
@ -51,12 +40,12 @@ ifdown()
echo "Error: Too many arguments. Usage: mwan3 ifdown <interface>" && exit 0
fi
ACTION=ifdown INTERFACE=$1 /sbin/hotplug-call iface
if [ -e /var/run/mwan3track-$1.pid ] ; then
kill $(cat /var/run/mwan3track-$1.pid)
rm /var/run/mwan3track-$1.pid
fi
ACTION=ifdown INTERFACE=$1 /sbin/hotplug-call iface
}
ifup()
@ -84,102 +73,46 @@ ifup()
interfaces()
{
local device enabled iface_id tracking
config_load mwan3
echo "Interface status:"
check_iface_status()
{
let iface_id++
device=$(uci -p /var/state get network.$1.ifname) &> /dev/null
if [ -z "$device" ]; then
echo " interface $1 is unknown"
return 0
fi
config_get enabled "$1" enabled 0
if [ -n "$(ps -w | grep mwan3track | grep -v grep | sed '/.*\/usr\/sbin\/mwan3track \([^ ]*\) .*$/!d;s//\1/' | awk '$1 == "'$1'"')" ]; then
tracking="active"
else
tracking="down"
fi
if [ -n "$($IP rule | awk '$5 == "'$device'"')" -a -n "$($IPT -S mwan3_iface_$1 2> /dev/null)" -a -n "$($IP route list table $iface_id default dev $device 2> /dev/null)" ]; then
if [ -n "$(uci -p /var/state get mwan3.$1.track_ip 2> /dev/null)" ]; then
echo " interface $1 is online (tracking $tracking)"
else
echo " interface $1 is online"
fi
elif [ -n "$($IP rule | awk '$5 == "'$device'"')" -o -n "$($IPT -S mwan3_iface_$1 2> /dev/null)" -o -n "$($IP route list table $iface_id default dev $device 2> /dev/null)" ]; then
echo " interface $1 error"
else
if [ "$enabled" -eq 1 ]; then
if [ -n "$(uci -p /var/state get mwan3.$1.track_ip 2> /dev/null)" ]; then
echo " interface $1 is offline (tracking $tracking)"
else
echo " interface $1 is offline"
fi
else
echo " interface $1 is disabled"
fi
fi
}
config_foreach check_iface_status interface
config_foreach mwan3_report_iface_status interface
echo -e
}
policies()
{
local percent policy share total_weight weight iface
for policy in $($IPT -S | awk '{print $2}' | grep mwan3_policy_ | sort -u); do
echo "Policy $policy:" | sed 's/mwan3_policy_//'
[ -n "$total_weight" ] || total_weight=$($IPT -S $policy | cut -s -d'"' -f2 | head -1 | awk '{print $3}')
if [ ! -z "${total_weight##*[!0-9]*}" ]; then
for iface in $($IPT -S $policy | cut -s -d'"' -f2 | awk '{print $1}'); do
weight=$($IPT -S $policy | cut -s -d'"' -f2 | awk '$1 == "'$iface'"' | awk '{print $2}')
percent=$(($weight*100/$total_weight))
echo " $iface ($percent%)"
done
else
echo " $($IPT -S $policy | sed '/.*--comment \([^ ]*\) .*$/!d;s//\1/;q')"
fi
echo -e
unset iface
unset total_weight
done
echo "Current ipv4 policies:"
mwan3_report_policies_v4
echo "Current ipv6 policies:"
mwan3_report_policies_v6
}
connected()
{
echo "Directly connected ipv4 networks:"
mwan3_report_connected_v4
echo -e
echo "Directly connected ipv6 networks:"
mwan3_report_connected_v6
echo -e
}
rules()
{
local address
if [ -n "$($IPT -S mwan3_connected 2> /dev/null)" ]; then
echo "Known networks:"
for address in $($IPS list mwan3_connected | egrep '[0-9]{1,3}(\.[0-9]{1,3}){3}'); do
echo " $address"
done
echo -e
fi
if [ -n "$($IPT -S mwan3_rules 2> /dev/null)" ]; then
echo "Active rules:"
$IPT -L mwan3_rules -n -v 2> /dev/null | tail -n+3 | sed 's/mark.*//' | sed 's/mwan3_policy_/- /' | sed 's/mwan3_rule_/S /'
echo -e
fi
echo "Active ipv4 user rules:"
mwan3_report_rules_v4
echo -e
echo "Active ipv6 user rules:"
mwan3_report_rules_v6
echo -e
}
status()
{
interfaces
policies
connected
rules
}
@ -191,31 +124,37 @@ start()
stop()
{
local ipset route rule table
local ipset route rule table IP IPT
killall mwan3track &> /dev/null
rm /var/run/mwan3track-* &> /dev/null
for route in $($IP route list table all | sed 's/.*table \([^ ]*\) .*/\1/' | awk '{print $1}' | awk '{for(i=1;i<=NF;i++) if($i+0>0) if($i+0<255) {print;break}}'); do
$IP route flush table $route &> /dev/null
for IP in "$IP4" "$IP6"; do
for route in $($IP route list table all | sed 's/.*table \([^ ]*\) .*/\1/' | awk '{print $1}' | awk '{for(i=1;i<=NF;i++) if($i+0>0) if($i+0<255) {print;break}}'); do
$IP route flush table $route &> /dev/null
done
for rule in $($IP rule list | egrep '^[1-2][0-9]{3}\:' | cut -d ':' -f 1); do
$IP rule del pref $rule &> /dev/null
done
done
for rule in $($IP rule list | egrep '^[1-2][0-9]{3}\:' | cut -d ':' -f 1); do
$IP rule del pref $rule &> /dev/null
for IPT in "$IPT4" "$IPT6"; do
$IPT -D PREROUTING -j mwan3_hook &> /dev/null
$IPT -D OUTPUT -j mwan3_hook &> /dev/null
for table in $($IPT -S | awk '{print $2}' | grep mwan3 | sort -u); do
$IPT -F $table &> /dev/null
done
for table in $($IPT -S | awk '{print $2}' | grep mwan3 | sort -u); do
$IPT -X $table &> /dev/null
done
done
$IPT -D PREROUTING -j mwan3_hook &> /dev/null
$IPT -D OUTPUT -j mwan3_hook &> /dev/null
for table in $($IPT -S | awk '{print $2}' | grep mwan3 | sort -u); do
$IPT -F $table &> /dev/null
done
for table in $($IPT -S | awk '{print $2}' | grep mwan3 | sort -u); do
$IPT -X $table &> /dev/null
done
for ipset in $(ipset -n list | grep mwan3); do
for ipset in $($IPS -n list | sort | grep mwan3); do
$IPS destroy $ipset
done
}
@ -226,7 +165,7 @@ restart() {
}
case "$1" in
ifup|ifdown|interfaces|policies|rules|status|start|stop|restart)
ifup|ifdown|interfaces|policies|connected|rules|status|start|stop|restart)
$*
;;
*)

View File

@ -17,7 +17,7 @@ lost=0
while true; do
for track_ip in $track_ips; do
ping -I $2 -c $4 -W $5 -s 4 -q $track_ip &> /dev/null
ping -I $2 -c $4 -W $5 -q $track_ip &> /dev/null
if [ $? -eq 0 ]; then
let host_up_count++
else