1
0
mirror of https://git.openwrt.org/feed/packages.git synced 2024-06-14 03:13:54 +02:00
openwrt-packages/net/mwan3/files/lib/mwan3/mwan3.sh

1249 lines
34 KiB
Bash
Raw Normal View History

#!/bin/sh
. "${IPKG_INSTROOT}/usr/share/libubox/jshn.sh"
. "${IPKG_INSTROOT}/lib/mwan3/common.sh"
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])"
IPv4_REGEX="((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)"
DEFAULT_LOWEST_METRIC=256
mwan3_push_update()
{
# helper function to build an update string to pass on to
# IPTR or IPS RESTORE. Modifies the 'update' variable in
# the local scope.
update="$update"$'\n'"$*";
}
mwan3_update_dev_to_table()
{
local _tid
# shellcheck disable=SC2034
mwan3_dev_tbl_ipv4=" "
# shellcheck disable=SC2034
mwan3_dev_tbl_ipv6=" "
update_table()
{
local family curr_table device enabled
let _tid++
config_get family "$1" family ipv4
network_get_device device "$1"
[ -z "$device" ] && return
config_get enabled "$1" enabled
[ "$enabled" -eq 0 ] && return
curr_table=$(eval "echo \"\$mwan3_dev_tbl_${family}\"")
export "mwan3_dev_tbl_$family=${curr_table}${device}=$_tid "
}
network_flush_cache
config_foreach update_table interface
}
mwan3_update_iface_to_table()
{
local _tid
mwan3_iface_tbl=" "
update_table()
{
let _tid++
export mwan3_iface_tbl="${mwan3_iface_tbl}${1}=$_tid "
}
config_foreach update_table interface
}
mwan3_route_line_dev()
{
# must have mwan3 config already loaded
# arg 1 is route device
local _tid route_line route_device route_family entry curr_table
route_line=$2
route_family=$3
route_device=$(echo "$route_line" | sed -ne "s/.*dev \([^ ]*\).*/\1/p")
unset "$1"
[ -z "$route_device" ] && return
curr_table=$(eval "echo \"\$mwan3_dev_tbl_${route_family}\"")
for entry in $curr_table; do
if [ "${entry%%=*}" = "$route_device" ]; then
_tid=${entry##*=}
export "$1=$_tid"
return
fi
done
}
# counts how many bits are set to 1
# n&(n-1) clears the lowest bit set to 1
mwan3_count_one_bits()
{
local count n
count=0
n=$(($1))
while [ "$n" -gt "0" ]; do
n=$((n&(n-1)))
count=$((count+1))
done
echo $count
}
mwan3_get_iface_id()
{
local _tmp
[ -z "$mwan3_iface_tbl" ] && mwan3_update_iface_to_table
_tmp="${mwan3_iface_tbl##* ${2}=}"
_tmp=${_tmp%% *}
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}' | grep -E "$IPv4_REGEX"); do
LOG notice "Adding network $custom_network_v4 from table $1 to mwan3_custom_v4 ipset"
mwan3_push_update -! add mwan3_custom_ipv4 "$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}' | grep -E "$IPv6_REGEX"); do
LOG notice "Adding network $custom_network_v6 from table $1 to mwan3_custom_v6 ipset"
mwan3_push_update -! add mwan3_custom_ipv6 "$custom_network_v6"
done
}
mwan3_set_custom_ipset()
{
local update=""
mwan3_push_update -! create mwan3_custom_ipv4 hash:net
mwan3_push_update flush mwan3_custom_ipv4
config_list_foreach "globals" "rt_table_lookup" mwan3_set_custom_ipset_v4
if [ $NO_IPV6 -eq 0 ]; then
mwan3_push_update -! create mwan3_custom_ipv6 hash:net family inet6
mwan3_push_update flush mwan3_custom_ipv6
config_list_foreach "globals" "rt_table_lookup" mwan3_set_custom_ipset_v6
fi
echo "$update" > "${MWAN3_STATUS_IPTABLES_LOG_DIR}/ipset-set_custom_ipset.dump"
error=$(echo "$update" | $IPS restore 2>&1) || LOG error "set_custom_ipset: $error"
}
mwan3_set_connected_ipv4()
{
local connected_network_v4 error
local candidate_list cidr_list
local update=""
mwan3_push_update -! create mwan3_connected_ipv4 hash:net
mwan3_push_update flush mwan3_connected_ipv4
candidate_list=""
cidr_list=""
route_lists()
{
$IP4 route | awk '{print $1}'
$IP4 route list table 0 | awk '{print $2}'
}
for connected_network_v4 in $(route_lists | grep -E "$IPv4_REGEX"); do
if [ -z "${connected_network_v4##*/*}" ]; then
cidr_list="$cidr_list $connected_network_v4"
else
candidate_list="$candidate_list $connected_network_v4"
fi
done
for connected_network_v4 in $cidr_list; do
mwan3_push_update -! add mwan3_connected_ipv4 "$connected_network_v4"
done
for connected_network_v4 in $candidate_list; do
mwan3_push_update -! add mwan3_connected_ipv4 "$connected_network_v4"
done
mwan3_push_update add mwan3_connected_ipv4 224.0.0.0/3
echo "$update" > "${MWAN3_STATUS_IPTABLES_LOG_DIR}/ipset-set_connected_ipv4.dump"
error=$(echo "$update" | $IPS restore 2>&1) || LOG error "set_connected_ipv4: $error"
}
mwan3_set_connected_ipv6()
{
local connected_network_v6 error
local update=""
[ $NO_IPV6 -eq 0 ] || return
mwan3_push_update -! create mwan3_connected_ipv6 hash:net family inet6
mwan3_push_update flush mwan3_connected_ipv6
for connected_network_v6 in $($IP6 route | awk '{print $1}' | grep -E "$IPv6_REGEX"); do
mwan3_push_update -! add mwan3_connected_ipv6 "$connected_network_v6"
done
echo "$update" > "${MWAN3_STATUS_IPTABLES_LOG_DIR}/ipset-set_connected_ipv6.dump"
error=$(echo "$update" | $IPS restore 2>&1) || LOG error "set_connected_ipv6: $error"
}
mwan3_set_connected_ipset()
{
local error
local update=""
mwan3_push_update -! create mwan3_connected_ipv4 hash:net
mwan3_push_update flush mwan3_connected_ipv4
if [ $NO_IPV6 -eq 0 ]; then
mwan3_push_update -! create mwan3_connected_ipv6 hash:net family inet6
mwan3_push_update flush mwan3_connected_ipv6
fi
echo "$update" > "${MWAN3_STATUS_IPTABLES_LOG_DIR}/ipset-set_connected_ipset.dump"
error=$(echo "$update" | $IPS restore 2>&1) || LOG error "set_connected_ipset: $error"
}
mwan3_set_dynamic_ipset()
{
local error
local update=""
mwan3_push_update -! create mwan3_dynamic_ipv4 list:set
mwan3_push_update flush mwan3_dynamic_ipv4
if [ $NO_IPV6 -eq 0 ]; then
mwan3_push_update -! create mwan3_dynamic_ipv6 hash:net family inet6
mwan3_push_update flush mwan3_dynamic_ipv6
fi
echo "$update" > "${MWAN3_STATUS_IPTABLES_LOG_DIR}/ipset-set_dynamic_ipset.dump"
error=$(echo "$update" | $IPS restore 2>&1) || LOG error "set_dynamic_ipset: $error"
}
mwan3_set_general_rules()
{
local IP
for IP in "$IP4" "$IP6"; do
[ "$IP" = "$IP6" ] && [ $NO_IPV6 -ne 0 ] && continue
RULE_NO=$((MM_BLACKHOLE+2000))
if [ -z "$($IP rule list | awk -v var="$RULE_NO:" '$1 == var')" ]; then
$IP rule add pref $RULE_NO fwmark $MMX_BLACKHOLE/$MMX_MASK blackhole
fi
RULE_NO=$((MM_UNREACHABLE+2000))
if [ -z "$($IP rule list | awk -v var="$RULE_NO:" '$1 == var')" ]; then
$IP rule add pref $RULE_NO fwmark $MMX_UNREACHABLE/$MMX_MASK unreachable
fi
done
}
mwan3_set_general_iptables()
{
local IPT current update error family
for IPT in "$IPT4" "$IPT6"; do
[ "$IPT" = "$IPT6" ] && [ $NO_IPV6 -ne 0 ] && continue
current="$($IPT -S)"$'\n'
update="*mangle"
if [ -n "${current##*-N mwan3_ifaces_in*}" ]; then
mwan3_push_update -N mwan3_ifaces_in
fi
if [ "$IPT" = "$IPT6" ]; then
family="ipv6"
else
family="ipv4"
fi
for chain in custom connected dynamic; do
echo "${current}" | grep -q "\-N mwan3_${chain}_${family}$"
local ret="$?"
if [ "$ret" = 1 ]; then
mwan3_push_update -N mwan3_${chain}_${family}
mwan3_push_update -A mwan3_${chain}_${family} \
-m set --match-set mwan3_${chain}_${family} dst \
-j MARK --set-xmark $MMX_DEFAULT/$MMX_MASK
fi
done
if [ -n "${current##*-N mwan3_rules*}" ]; then
mwan3_push_update -N mwan3_rules
fi
if [ -n "${current##*-N mwan3_hook*}" ]; then
mwan3_push_update -N mwan3_hook
# do not mangle ipv6 ra service
if [ "$IPT" = "$IPT6" ]; then
mwan3_push_update -A mwan3_hook \
-p ipv6-icmp \
-m icmp6 --icmpv6-type 133 \
-j RETURN
mwan3_push_update -A mwan3_hook \
-p ipv6-icmp \
-m icmp6 --icmpv6-type 134 \
-j RETURN
mwan3_push_update -A mwan3_hook \
-p ipv6-icmp \
-m icmp6 --icmpv6-type 135 \
-j RETURN
mwan3_push_update -A mwan3_hook \
-p ipv6-icmp \
-m icmp6 --icmpv6-type 136 \
-j RETURN
mwan3_push_update -A mwan3_hook \
-p ipv6-icmp \
-m icmp6 --icmpv6-type 137 \
-j RETURN
fi
mwan3_push_update -A mwan3_hook \
-m mark --mark 0x0/$MMX_MASK \
-j CONNMARK --restore-mark --nfmask "$MMX_MASK" --ctmask "$MMX_MASK"
mwan3_push_update -A mwan3_hook \
-m mark --mark 0x0/$MMX_MASK \
-j mwan3_ifaces_in
for chain in custom connected dynamic; do
mwan3_push_update -A mwan3_hook \
-m mark --mark 0x0/$MMX_MASK \
-j mwan3_${chain}_${family}
done
mwan3_push_update -A mwan3_hook \
-m mark --mark 0x0/$MMX_MASK \
-j mwan3_rules
mwan3_push_update -A mwan3_hook \
-j CONNMARK --save-mark --nfmask "$MMX_MASK" --ctmask "$MMX_MASK"
for chain in custom connected dynamic; do
mwan3_push_update -A mwan3_hook \
-m mark ! --mark $MMX_DEFAULT/$MMX_MASK \
-j mwan3_${chain}_${family}
done
fi
if [ -n "${current##*-N mwan3_pre*}" ]; then
mwan3_push_update -N mwan3_pre
mwan3_push_update -A mwan3_pre \
-j MARK --set-xmark "0x0/$MMX_MASK"
fi
if [ -n "${current##*-N mwan3_post*}" ]; then
mwan3_push_update -N mwan3_post
mwan3_push_update -A mwan3_post \
-j MARK --set-xmark "0x0/$MMX_MASK"
fi
if [ -n "${current##*-A PREROUTING -j mwan3_pre*}" ]; then
mwan3_push_update -A PREROUTING -j mwan3_pre
fi
if [ -n "${current##*-A PREROUTING -j mwan3_hook*}" ]; then
mwan3_push_update -A PREROUTING -j mwan3_hook
fi
if [ -n "${current##*-A OUTPUT -j mwan3_hook*}" ]; then
mwan3_push_update -A OUTPUT -j mwan3_hook
fi
if [ -n "${current##*-A POSTROUTING -j mwan3_post*}" ]; then
mwan3_push_update -A POSTROUTING -j mwan3_post
fi
mwan3_push_update COMMIT
mwan3_push_update ""
echo "$update" > "${MWAN3_STATUS_IPTABLES_LOG_DIR}/iptables-set_general_iptables-${family}.dump"
if [ "$IPT" = "$IPT4" ]; then
error=$(echo "$update" | $IPT4R 2>&1) || LOG error "set_general_iptables (${family}): $error"
else
error=$(echo "$update" | $IPT6R 2>&1) || LOG error "set_general_iptables (${family}): $error"
fi
done
}
mwan3_create_iface_iptables()
{
local id family IPT IPTR current update error
config_get family "$1" family ipv4
mwan3_get_iface_id id "$1"
[ -n "$id" ] || return 0
if [ "$family" = "ipv4" ]; then
IPT="$IPT4"
IPTR="$IPT4R"
elif [ "$family" = "ipv6" ] && [ $NO_IPV6 -eq 0 ]; then
IPT="$IPT6"
IPTR="$IPT6R"
else
return
fi
current="$($IPT -S)"$'\n'
update="*mangle"
if [ -n "${current##*-N mwan3_ifaces_in*}" ]; then
mwan3_push_update -N mwan3_ifaces_in
fi
if [ -n "${current##*-N mwan3_iface_in_$1$'\n'*}" ]; then
mwan3_push_update -N "mwan3_iface_in_$1"
else
mwan3_push_update -F "mwan3_iface_in_$1"
fi
for chain in custom connected dynamic; do
mwan3_push_update -A "mwan3_iface_in_$1" \
-i "$2" \
-m set --match-set mwan3_${chain}_${family} src \
-m mark --mark "0x0/$MMX_MASK" \
-m comment --comment "default" \
-j MARK --set-xmark "$MMX_DEFAULT/$MMX_MASK"
done
mwan3_push_update -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"
if [ -n "${current##*-A mwan3_ifaces_in -m mark --mark 0x0/$MMX_MASK -j mwan3_iface_in_${1}$'\n'*}" ]; then
mwan3_push_update -A mwan3_ifaces_in \
-m mark --mark 0x0/$MMX_MASK \
-j "mwan3_iface_in_$1"
LOG debug "create_iface_iptables: mwan3_iface_in_$1 not in iptables, adding"
else
LOG debug "create_iface_iptables: mwan3_iface_in_$1 already in iptables, skip"
fi
mwan3_push_update COMMIT
mwan3_push_update ""
echo "$update" > "${MWAN3_STATUS_IPTABLES_LOG_DIR}/iptables-create_iface_iptables-${1}.dump"
error=$(echo "$update" | $IPTR 2>&1) || LOG error "create_iface_iptables (${1}): $error"
}
mwan3_delete_iface_iptables()
{
local IPT update
config_get family "$1" family ipv4
if [ "$family" = "ipv4" ]; then
IPT="$IPT4"
fi
if [ "$family" = "ipv6" ]; then
[ $NO_IPV6 -ne 0 ] && return
IPT="$IPT6"
fi
update="*mangle"
mwan3_push_update -D mwan3_ifaces_in \
-m mark --mark 0x0/$MMX_MASK \
-j "mwan3_iface_in_$1" &> /dev/null
mwan3_push_update -F "mwan3_iface_in_$1" &> /dev/null
mwan3_push_update -X "mwan3_iface_in_$1" &> /dev/null
mwan3_push_update COMMIT
mwan3_push_update ""
echo "$update" > "${MWAN3_STATUS_IPTABLES_LOG_DIR}/iptables-delete_iface_iptables-${1}.dump"
error=$(echo "$update" | $IPTR 2>&1) || LOG error "delete_iface_iptables (${1}): $error"
}
mwan3_extra_tables_routes()
{
$IP route list table "$1"
}
mwan3_get_routes()
{
{
$IP route list table main
config_list_foreach "globals" "rt_table_lookup" mwan3_extra_tables_routes
} | sed -ne "$MWAN3_ROUTE_LINE_EXP" | sort -u
}
mwan3_create_iface_route()
{
local tid route_line family IP id tbl
config_get family "$1" family ipv4
mwan3_get_iface_id id "$1"
[ -n "$id" ] || return 0
if [ "$family" = "ipv4" ]; then
IP="$IP4"
elif [ "$family" = "ipv6" ]; then
IP="$IP6"
fi
tbl=$($IP route list table $id 2>/dev/null)$'\n'
mwan3_update_dev_to_table
mwan3_get_routes | while read -r route_line; do
mwan3_route_line_dev "tid" "$route_line" "$family"
{ [ -z "${route_line##default*}" ] || [ -z "${route_line##fe80::/64*}" ]; } && [ "$tid" != "$id" ] && continue
if [ -z "$tid" ] || [ "$tid" = "$id" ]; then
# possible that routes are already in the table
# if 'connected' was called after 'ifup'
[ -n "$tbl" ] && [ -z "${tbl##*$route_line$'\n'*}" ] && continue
$IP route add table $id $route_line ||
LOG debug "Route '$route_line' already added to table $id"
fi
done
}
mwan3_delete_iface_route()
{
local id family
config_get family "$1" family ipv4
mwan3_get_iface_id id "$1"
if [ -z "$id" ]; then
LOG warn "delete_iface_route: could not find table id for interface $1"
return 0
fi
if [ "$family" = "ipv4" ]; then
$IP4 route flush table "$id"
elif [ "$family" = "ipv6" ] && [ $NO_IPV6 -eq 0 ]; then
$IP6 route flush table "$id"
fi
}
mwan3_create_iface_rules()
{
local id family IP
config_get family "$1" family ipv4
mwan3_get_iface_id id "$1"
[ -n "$id" ] || return 0
if [ "$family" = "ipv4" ]; then
IP="$IP4"
elif [ "$family" = "ipv6" ] && [ $NO_IPV6 -eq 0 ]; then
IP="$IP6"
else
return
fi
mwan3_delete_iface_rules "$1"
$IP rule add pref $((id+1000)) iif "$2" lookup "$id"
$IP rule add pref $((id+2000)) fwmark "$(mwan3_id2mask id MMX_MASK)/$MMX_MASK" lookup "$id"
$IP rule add pref $((id+3000)) fwmark "$(mwan3_id2mask id MMX_MASK)/$MMX_MASK" unreachable
}
mwan3_delete_iface_rules()
{
local id family IP rule_id
config_get family "$1" family ipv4
mwan3_get_iface_id id "$1"
[ -n "$id" ] || return 0
if [ "$family" = "ipv4" ]; then
IP="$IP4"
elif [ "$family" = "ipv6" ] && [ $NO_IPV6 -eq 0 ]; then
IP="$IP6"
else
return
fi
for rule_id in $(ip rule list | awk '$1 % 1000 == '$id' && $1 > 1000 && $1 < 4000 {print substr($1,0,4)}'); do
$IP rule del pref $rule_id
done
}
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_rule_); do
for entry in $(ipset list "$setname" | grep "$(mwan3_id2mask id MMX_MASK | awk '{ printf "0x%08x", $1; }')" | cut -d ' ' -f 1); do
$IPS del "$setname" $entry ||
LOG notice "failed to delete $entry from $setname"
done
done
}
mwan3_set_policy()
{
local id iface family metric probability weight device is_lowest is_offline IPT IPTR total_weight current update error
is_lowest=0
config_get iface "$1" interface
config_get metric "$1" metric 1
config_get weight "$1" weight 1
[ -n "$iface" ] || return 0
network_get_device device "$iface"
[ "$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"
[ -n "$id" ] || return 0
[ "$(mwan3_get_iface_hotplug_state "$iface")" = "online" ]
is_offline=$?
config_get family "$iface" family ipv4
if [ "$family" = "ipv4" ]; then
IPT="$IPT4"
IPTR="$IPT4R"
elif [ "$family" = "ipv6" ]; then
IPT="$IPT6"
IPTR="$IPT6R"
fi
current="$($IPT -S)"$'\n'
update="*mangle"
if [ "$family" = "ipv4" ] && [ $is_offline -eq 0 ]; then
if [ "$metric" -lt "$lowest_metric_v4" ]; then
is_lowest=1
total_weight_v4=$weight
lowest_metric_v4=$metric
elif [ "$metric" -eq "$lowest_metric_v4" ]; then
total_weight_v4=$((total_weight_v4+weight))
total_weight=$total_weight_v4
else
return
fi
elif [ "$family" = "ipv6" ] && [ $NO_IPV6 -eq 0 ] && [ $is_offline -eq 0 ]; then
if [ "$metric" -lt "$lowest_metric_v6" ]; then
is_lowest=1
total_weight_v6=$weight
lowest_metric_v6=$metric
elif [ "$metric" -eq "$lowest_metric_v6" ]; then
total_weight_v6=$((total_weight_v6+weight))
total_weight=$total_weight_v6
else
return
fi
fi
if [ $is_lowest -eq 1 ]; then
mwan3_push_update -F "mwan3_policy_$policy"
mwan3_push_update -A "mwan3_policy_$policy" \
-m mark --mark 0x0/$MMX_MASK \
-m comment --comment \"$iface $weight $weight\" \
-j MARK --set-xmark "$(mwan3_id2mask id MMX_MASK)/$MMX_MASK"
elif [ $is_offline -eq 0 ]; then
probability=$((weight*1000/total_weight))
if [ "$probability" -lt 10 ]; then
probability="0.00$probability"
elif [ $probability -lt 100 ]; then
probability="0.0$probability"
elif [ $probability -lt 1000 ]; then
probability="0.$probability"
else
probability="1"
fi
mwan3_push_update -I "mwan3_policy_$policy" \
-m mark --mark 0x0/$MMX_MASK \
-m statistic \
--mode random \
--probability "$probability" \
-m comment --comment \"$iface $weight $total_weight\" \
-j MARK --set-xmark "$(mwan3_id2mask id MMX_MASK)/$MMX_MASK"
elif [ -n "$device" ]; then
echo "$current" | grep -q "^-A mwan3_policy_$policy.*--comment .* [0-9]* [0-9]*" ||
mwan3_push_update -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
mwan3_push_update COMMIT
mwan3_push_update ""
echo "$update" > "${MWAN3_STATUS_IPTABLES_LOG_DIR}/iptables-set_policy-${1}.dump"
error=$(echo "$update" | $IPTR 2>&1) || LOG error "set_policy ($1): $error"
}
mwan3_create_policies_iptables()
{
local last_resort lowest_metric_v4 lowest_metric_v6 total_weight_v4 total_weight_v6 policy IPT current update error
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
[ "$IPT" = "$IPT6" ] && [ $NO_IPV6 -ne 0 ] && continue
current="$($IPT -S)"$'\n'
update="*mangle"
if [ -n "${current##*-N mwan3_policy_$1$'\n'*}" ]; then
mwan3_push_update -N "mwan3_policy_$1"
fi
mwan3_push_update -F "mwan3_policy_$1"
case "$last_resort" in
blackhole)
mwan3_push_update -A "mwan3_policy_$1" \
-m mark --mark 0x0/$MMX_MASK \
-m comment --comment "blackhole" \
-j MARK --set-xmark $MMX_BLACKHOLE/$MMX_MASK
;;
default)
mwan3_push_update -A "mwan3_policy_$1" \
-m mark --mark 0x0/$MMX_MASK \
-m comment --comment "default" \
-j MARK --set-xmark $MMX_DEFAULT/$MMX_MASK
;;
*)
mwan3_push_update -A "mwan3_policy_$1" \
-m mark --mark 0x0/$MMX_MASK \
-m comment --comment "unreachable" \
-j MARK --set-xmark $MMX_UNREACHABLE/$MMX_MASK
;;
esac
mwan3_push_update COMMIT
mwan3_push_update ""
echo "$update" > "${MWAN3_STATUS_IPTABLES_LOG_DIR}/iptables-create_policies_iptables-${1}.dump"
if [ "$IPT" = "$IPT4" ]; then
error=$(echo "$update" | $IPT4R 2>&1) || LOG error "create_policies_iptables ($1): $error"
else
error=$(echo "$update" | $IPT6R 2>&1) || LOG error "create_policies_iptables ($1): $error"
fi
done
lowest_metric_v4=$DEFAULT_LOWEST_METRIC
total_weight_v4=0
lowest_metric_v6=$DEFAULT_LOWEST_METRIC
total_weight_v6=0
config_list_foreach "$1" use_member mwan3_set_policy
}
mwan3_set_policies_iptables()
{
config_foreach mwan3_create_policies_iptables policy
}
mwan3_set_sticky_iptables()
{
local rule="${1}"
local interface="${2}"
local ipv="${3}"
local policy="${4}"
local id iface
for iface in $(echo "$current" | grep "^-A $policy" | cut -s -d'"' -f2 | awk '{print $1}'); do
if [ "$iface" = "$interface" ]; then
mwan3_get_iface_id id "$iface"
[ -n "$id" ] || return 0
if [ -z "${current##*-N mwan3_iface_in_${iface}$'\n'*}" ]; then
mwan3_push_update -I "mwan3_rule_$rule" \
-m mark --mark "$(mwan3_id2mask id MMX_MASK)/$MMX_MASK" \
-m set ! --match-set "mwan3_rule_${ipv}_${rule}" src,src \
-j MARK --set-xmark "0x0/$MMX_MASK"
mwan3_push_update -I "mwan3_rule_$rule" \
-m mark --mark "0/$MMX_MASK" \
-j MARK --set-xmark "$(mwan3_id2mask id MMX_MASK)/$MMX_MASK"
fi
fi
done
}
mwan3_set_sticky_ipset()
{
local rule="$1"
local mmx="$2"
local timeout="$3"
local error
local update=""
mwan3_push_update -! create "mwan3_rule_ipv4_$rule" \
hash:ip,mark markmask "$mmx" \
timeout "$timeout"
[ $NO_IPV6 -eq 0 ] &&
mwan3_push_update -! create "mwan3_rule_ipv6_$rule" \
hash:ip,mark markmask "$mmx" \
timeout "$timeout" family inet6
echo "$update" > "${MWAN3_STATUS_IPTABLES_LOG_DIR}/ipset-set_sticky_ipset-${rule}.dump"
error=$(echo "$update" | $IPS restore 2>&1) || LOG error "set_sticky_ipset (${rule}): $error"
}
mwan3_set_user_iptables_rule()
{
local ipset family proto policy src_ip src_port src_iface src_dev
local sticky dest_ip dest_port use_policy timeout policy
local global_logging rule_logging loglevel rule_policy rule ipv
rule="$1"
ipv="$2"
rule_policy=0
config_get sticky "$1" sticky 0
config_get timeout "$1" timeout 600
config_get ipset "$1" ipset
config_get proto "$1" proto all
config_get src_ip "$1" src_ip
config_get src_iface "$1" src_iface
config_get src_port "$1" src_port
config_get dest_ip "$1" dest_ip
config_get dest_port "$1" dest_port
config_get use_policy "$1" use_policy
config_get family "$1" family any
config_get rule_logging "$1" logging 0
config_get global_logging globals logging 0
config_get loglevel globals loglevel notice
[ "$ipv" = "ipv6" ] && [ $NO_IPV6 -ne 0 ] && return
[ "$family" = "ipv4" ] && [ "$ipv" = "ipv6" ] && return
[ "$family" = "ipv6" ] && [ "$ipv" = "ipv4" ] && return
for ipaddr in "$src_ip" "$dest_ip"; do
if [ -n "$ipaddr" ] && { { [ "$ipv" = "ipv4" ] && echo "$ipaddr" | grep -qE "$IPv6_REGEX"; } ||
{ [ "$ipv" = "ipv6" ] && echo "$ipaddr" | grep -qE $IPv4_REGEX; } }; then
LOG warn "invalid $ipv address $ipaddr specified for rule $rule"
return
fi
done
if [ -n "$src_iface" ]; then
network_get_device src_dev "$src_iface"
if [ -z "$src_dev" ]; then
LOG notice "could not find device corresponding to src_iface $src_iface for rule $1"
return
fi
fi
[ -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
if [ "$proto" != 'tcp' ] && [ "$proto" != 'udp' ]; then
[ -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
fi
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
ipset="-m set --match-set $ipset dst"
fi
if [ -z "$use_policy" ]; then
return
fi
if [ "$use_policy" = "default" ]; then
policy="MARK --set-xmark $MMX_DEFAULT/$MMX_MASK"
elif [ "$use_policy" = "unreachable" ]; then
policy="MARK --set-xmark $MMX_UNREACHABLE/$MMX_MASK"
elif [ "$use_policy" = "blackhole" ]; then
policy="MARK --set-xmark $MMX_BLACKHOLE/$MMX_MASK"
else
rule_policy=1
policy="mwan3_policy_$use_policy"
if [ "$sticky" -eq 1 ]; then
mwan3_set_sticky_ipset "$rule" "$MMX_MASK" "$timeout"
fi
fi
if [ $rule_policy -eq 1 ] && [ -n "${current##*-N $policy$'\n'*}" ]; then
mwan3_push_update -N "$policy"
fi
if [ $rule_policy -eq 1 ] && [ "$sticky" -eq 1 ]; then
if [ -n "${current##*-N mwan3_rule_$1$'\n'*}" ]; then
mwan3_push_update -N "mwan3_rule_$1"
fi
mwan3_push_update -F "mwan3_rule_$1"
config_foreach mwan3_set_sticky_iptables interface $ipv "$policy"
mwan3_push_update -A "mwan3_rule_$1" \
-m mark --mark 0/$MMX_MASK \
-j "$policy"
mwan3_push_update -A "mwan3_rule_$1" \
-m mark ! --mark 0xfc00/0xfc00 \
-j SET --del-set "mwan3_rule_${ipv}_${rule}" src,src
mwan3_push_update -A "mwan3_rule_$1" \
-m mark ! --mark 0xfc00/0xfc00 \
-j SET --add-set "mwan3_rule_${ipv}_${rule}" src,src
policy="mwan3_rule_$1"
fi
if [ "$global_logging" = "1" ] && [ "$rule_logging" = "1" ]; then
mwan3_push_update -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)"
fi
mwan3_push_update -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
}
mwan3_set_user_iface_rules()
{
local current iface update family error device is_src_iface
iface=$1
device=$2
if [ -z "$device" ]; then
LOG notice "set_user_iface_rules: could not find device corresponding to iface $iface"
return
fi
config_get family "$iface" family ipv4
if [ "$family" = "ipv4" ]; then
IPT="$IPT4"
IPTR="$IPT4R"
elif [ "$family" = "ipv6" ]; then
IPT="$IPT6"
IPTR="$IPT6R"
fi
$IPT -S | grep -q "^-A mwan3_rules.*-i $device" && return
is_src_iface=0
iface_rule()
{
local src_iface
config_get src_iface "$1" src_iface
[ "$src_iface" = "$iface" ] && is_src_iface=1
}
config_foreach iface_rule rule
[ $is_src_iface -eq 1 ] && mwan3_set_user_rules
}
mwan3_set_user_rules()
{
local IPT IPTR ipv
local current update error
for ipv in ipv4 ipv6; do
if [ "$ipv" = "ipv4" ]; then
IPT="$IPT4"
IPTR="$IPT4R"
elif [ "$ipv" = "ipv6" ]; then
IPT="$IPT6"
IPTR="$IPT6R"
fi
[ "$ipv" = "ipv6" ] && [ $NO_IPV6 -ne 0 ] && continue
update="*mangle"
current="$($IPT -S)"$'\n'
if [ -n "${current##*-N mwan3_rules*}" ]; then
mwan3_push_update -N "mwan3_rules"
fi
mwan3_push_update -F mwan3_rules
config_foreach mwan3_set_user_iptables_rule rule "$ipv"
mwan3_push_update COMMIT
mwan3_push_update ""
echo "$update" > "${MWAN3_STATUS_IPTABLES_LOG_DIR}/iptables-set_user_rules-${ipv}.dump"
error=$(echo "$update" | $IPTR 2>&1) || LOG error "set_user_rules (${ipv}): $error"
done
}
mwan3_interface_hotplug_shutdown()
{
local interface status device ifdown
interface="$1"
ifdown="$2"
[ -f $MWAN3TRACK_STATUS_DIR/$interface/STATUS ] && {
status=$(cat $MWAN3TRACK_STATUS_DIR/$interface/STATUS)
}
[ "$status" != "online" ] && [ "$ifdown" != 1 ] && return
if [ "$ifdown" = 1 ]; then
env -i ACTION=ifdown \
INTERFACE=$interface \
DEVICE=$device \
sh /etc/hotplug.d/iface/15-mwan3
else
[ "$status" = "online" ] && {
env -i MWAN3_SHUTDOWN="1" \
ACTION="disconnected" \
INTERFACE="$interface" \
DEVICE="$device" /sbin/hotplug-call iface
}
fi
}
mwan3_interface_shutdown()
{
mwan3_interface_hotplug_shutdown $1
mwan3_track_clean $1
}
mwan3_ifup()
{
local interface=$1
local caller=$2
local up l3_device status true_iface
if [ "${caller}" = "cmd" ]; then
# It is not necessary to obtain a lock here, because it is obtained in the hotplug
# script, but we still want to do the check to print a useful error message
/etc/init.d/mwan3 running || {
echo 'The service mwan3 is global disabled.'
echo 'Please execute "/etc/init.d/mwan3 start" first.'
exit 1
}
config_load mwan3
fi
mwan3_get_true_iface true_iface $interface
status=$(ubus -S call network.interface.$true_iface status)
[ -n "$status" ] && {
json_load "$status"
json_get_vars up l3_device
}
hotplug_startup()
{
env -i MWAN3_STARTUP=$caller ACTION=ifup \
INTERFACE=$interface DEVICE=$l3_device \
sh /etc/hotplug.d/iface/15-mwan3
}
if [ "$up" != "1" ] || [ -z "$l3_device" ]; then
return
fi
if [ "${caller}" = "init" ]; then
hotplug_startup &
hotplug_pids="$hotplug_pids $!"
else
hotplug_startup
fi
}
mwan3: fix interface-bound traffic when interface is offline This commit fixed what 6d99b602 was supposed to fix without affecting interface-bound traffic. Before 6d99b602 interface-bound traffic was working normally as long as at least one interface was online. However when the last interface went offline, it was impossible to ping and such state was unrecoverable. Commit 6d99b602 fixed unrecoverable offline state problem (it was possible to ping -I iface) but messed inteface-bound traffic. Traffic with interface source address was not working if the interface was in "offline" state, even if another interface was online. The problem was caused by an inconsistent "offline" interface state: iptables-related rules were kept while routing table and policy were deleted. The idea behind this commit is to: 1. Keep all the rules for each interface (iptables, routing table, policy) regardless of its state. This ensures consistency, 2. Make interface state hotplug events affect only iptables' mwan3_policy_* rules. Interface-related iptables, routing table and policy is removed only when mwan3 is manually stopped. To make such changes possible, it's necessary to change the way mwan3_policy_* rule generator keeps track of interface state hotplug events. Until now, it checked for the existence of custom interface-related routing table (table id 1, 2, 3, ...). Clearly we can no longer rely on that so each interface state is stored explicitly in file. Signed-off-by: Marcin Jurkowski <marcin1j@gmail.com>
2017-09-03 00:56:09 +02:00
mwan3_set_iface_hotplug_state() {
local iface=$1
local state=$2
echo "$state" > "$MWAN3_STATUS_DIR/iface_state/$iface"
mwan3: fix interface-bound traffic when interface is offline This commit fixed what 6d99b602 was supposed to fix without affecting interface-bound traffic. Before 6d99b602 interface-bound traffic was working normally as long as at least one interface was online. However when the last interface went offline, it was impossible to ping and such state was unrecoverable. Commit 6d99b602 fixed unrecoverable offline state problem (it was possible to ping -I iface) but messed inteface-bound traffic. Traffic with interface source address was not working if the interface was in "offline" state, even if another interface was online. The problem was caused by an inconsistent "offline" interface state: iptables-related rules were kept while routing table and policy were deleted. The idea behind this commit is to: 1. Keep all the rules for each interface (iptables, routing table, policy) regardless of its state. This ensures consistency, 2. Make interface state hotplug events affect only iptables' mwan3_policy_* rules. Interface-related iptables, routing table and policy is removed only when mwan3 is manually stopped. To make such changes possible, it's necessary to change the way mwan3_policy_* rule generator keeps track of interface state hotplug events. Until now, it checked for the existence of custom interface-related routing table (table id 1, 2, 3, ...). Clearly we can no longer rely on that so each interface state is stored explicitly in file. Signed-off-by: Marcin Jurkowski <marcin1j@gmail.com>
2017-09-03 00:56:09 +02:00
}
mwan3_get_iface_hotplug_state() {
local iface=$1
cat "$MWAN3_STATUS_DIR/iface_state/$iface" 2>/dev/null || echo "offline"
mwan3: fix interface-bound traffic when interface is offline This commit fixed what 6d99b602 was supposed to fix without affecting interface-bound traffic. Before 6d99b602 interface-bound traffic was working normally as long as at least one interface was online. However when the last interface went offline, it was impossible to ping and such state was unrecoverable. Commit 6d99b602 fixed unrecoverable offline state problem (it was possible to ping -I iface) but messed inteface-bound traffic. Traffic with interface source address was not working if the interface was in "offline" state, even if another interface was online. The problem was caused by an inconsistent "offline" interface state: iptables-related rules were kept while routing table and policy were deleted. The idea behind this commit is to: 1. Keep all the rules for each interface (iptables, routing table, policy) regardless of its state. This ensures consistency, 2. Make interface state hotplug events affect only iptables' mwan3_policy_* rules. Interface-related iptables, routing table and policy is removed only when mwan3 is manually stopped. To make such changes possible, it's necessary to change the way mwan3_policy_* rule generator keeps track of interface state hotplug events. Until now, it checked for the existence of custom interface-related routing table (table id 1, 2, 3, ...). Clearly we can no longer rely on that so each interface state is stored explicitly in file. Signed-off-by: Marcin Jurkowski <marcin1j@gmail.com>
2017-09-03 00:56:09 +02:00
}
mwan3_report_iface_status()
{
local device result tracking IP IPT error
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" ] || [ -z "$device" ]; then
result="offline"
else
error=0
[ -n "$($IP rule | awk '$1 == "'$((id+1000)):'"')" ] ||
error=$((error+1))
[ -n "$($IP rule | awk '$1 == "'$((id+2000)):'"')" ] ||
error=$((error+2))
[ -n "$($IP rule | awk '$1 == "'$((id+3000)):'"')" ] ||
error=$((error+4))
[ -n "$($IPT -S mwan3_iface_in_$1 2> /dev/null)" ] ||
error=$((error+8))
[ -n "$($IP route list table $id default dev $device 2> /dev/null)" ] ||
error=$((error+16))
fi
if [ "$result" = "offline" ]; then
:
elif [ $error -eq 0 ]; then
online=$(get_online_time "$1")
network_get_uptime uptime "$1"
online="$(printf '%02dh:%02dm:%02ds\n' $((online/3600)) $((online%3600/60)) $((online%60)))"
uptime="$(printf '%02dh:%02dm:%02ds\n' $((uptime/3600)) $((uptime%3600/60)) $((uptime%60)))"
result="$(mwan3_get_iface_hotplug_state $1) $online, uptime $uptime"
elif [ $error -gt 0 ] && [ $error -ne 31 ]; then
result="error (${error})"
elif [ "$enabled" = "1" ]; then
mwan3: fix interface-bound traffic when interface is offline This commit fixed what 6d99b602 was supposed to fix without affecting interface-bound traffic. Before 6d99b602 interface-bound traffic was working normally as long as at least one interface was online. However when the last interface went offline, it was impossible to ping and such state was unrecoverable. Commit 6d99b602 fixed unrecoverable offline state problem (it was possible to ping -I iface) but messed inteface-bound traffic. Traffic with interface source address was not working if the interface was in "offline" state, even if another interface was online. The problem was caused by an inconsistent "offline" interface state: iptables-related rules were kept while routing table and policy were deleted. The idea behind this commit is to: 1. Keep all the rules for each interface (iptables, routing table, policy) regardless of its state. This ensures consistency, 2. Make interface state hotplug events affect only iptables' mwan3_policy_* rules. Interface-related iptables, routing table and policy is removed only when mwan3 is manually stopped. To make such changes possible, it's necessary to change the way mwan3_policy_* rule generator keeps track of interface state hotplug events. Until now, it checked for the existence of custom interface-related routing table (table id 1, 2, 3, ...). Clearly we can no longer rely on that so each interface state is stored explicitly in file. Signed-off-by: Marcin Jurkowski <marcin1j@gmail.com>
2017-09-03 00:56:09 +02:00
result="offline"
else
mwan3: fix interface-bound traffic when interface is offline This commit fixed what 6d99b602 was supposed to fix without affecting interface-bound traffic. Before 6d99b602 interface-bound traffic was working normally as long as at least one interface was online. However when the last interface went offline, it was impossible to ping and such state was unrecoverable. Commit 6d99b602 fixed unrecoverable offline state problem (it was possible to ping -I iface) but messed inteface-bound traffic. Traffic with interface source address was not working if the interface was in "offline" state, even if another interface was online. The problem was caused by an inconsistent "offline" interface state: iptables-related rules were kept while routing table and policy were deleted. The idea behind this commit is to: 1. Keep all the rules for each interface (iptables, routing table, policy) regardless of its state. This ensures consistency, 2. Make interface state hotplug events affect only iptables' mwan3_policy_* rules. Interface-related iptables, routing table and policy is removed only when mwan3 is manually stopped. To make such changes possible, it's necessary to change the way mwan3_policy_* rule generator keeps track of interface state hotplug events. Until now, it checked for the existence of custom interface-related routing table (table id 1, 2, 3, ...). Clearly we can no longer rely on that so each interface state is stored explicitly in file. Signed-off-by: Marcin Jurkowski <marcin1j@gmail.com>
2017-09-03 00:56:09 +02:00
result="disabled"
fi
tracking="$(mwan3_get_mwan3track_status $1)"
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 [ -n "${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 policy
for policy in $($IPT4 -S | awk '{print $2}' | grep mwan3_policy_ | sort -u); do
echo "$policy:" | sed 's/mwan3_policy_//'
mwan3_report_policies "$IPT4" "$policy"
done
}
mwan3_report_policies_v6()
{
local policy
for policy in $($IPT6 -S | awk '{print $2}' | grep mwan3_policy_ | sort -u); do
echo "$policy:" | sed 's/mwan3_policy_//'
mwan3_report_policies "$IPT6" "$policy"
done
}
mwan3_report_connected_v4()
{
if [ -n "$($IPT4 -S mwan3_connected_ipv4 2> /dev/null)" ]; then
$IPS -o save list mwan3_connected_ipv4 | grep add | cut -d " " -f 3
fi
}
mwan3_report_connected_v6()
{
if [ -n "$($IPT6 -S mwan3_connected_ipv6 2> /dev/null)" ]; then
$IPS -o save list mwan3_connected_ipv6 | grep add | cut -d " " -f 3
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
}
mwan3_flush_conntrack()
{
local interface="$1"
local action="$2"
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
config_list_foreach "$interface" flush_conntrack handle_flush "$action"
fi
}
mwan3_track_clean()
{
rm -rf "${MWAN3_STATUS_DIR:?}/${1}" &> /dev/null
rmdir --ignore-fail-on-non-empty "$MWAN3_STATUS_DIR"
}