#!/bin/sh
#
# Copyright (C) 2018-2025 Ycarus (Yannick Chabanois) <ycarus@zugaina.org> for OpenMPTCProuter
#
# This is free software, licensed under the GNU General Public License v2.
# See /LICENSE for more information.
#
# This script do commands when an interface is detected as up

if [ "$OMR_TRACKER_STATUS" = "ERROR" ]; then
	exit 0
fi

#if [ "$OMR_TRACKER_INTERFACE" != "omrvpn" ] && [ "$OMR_TRACKER_INTERFACE" != "omr6in4" ] && [ "$OMR_TRACKER_PREV_STATUS" = "$OMR_TRACKER_STATUS" ] && [ -n "$OMR_TRACKER_INTERFACE" ] && [ "$OMR_TRACKER_PREV_DEVICE_IP" = "$OMR_TRACKER_DEVICE_IP" ] && [ "$OMR_TRACKER_PREV_DEVICE_IP6" = "$OMR_TRACKER_DEVICE_IP6" ] && (([ -n "$OMR_TRACKER_DEVICE_GATEWAY" ] && [ -n "$(ip r show table 991337)" ]) || ([ -n "$OMR_TRACKER_DEVICE_GATEWAY6" ] && [ -n "$(ip -6 r show table 6991337)" ])); then
#	exit 0
#fi

SETROUTE=false

. "${OMR_LIB_DIR:-/usr/share/omr/lib}/common-post-tracking.sh"

# Prevent overlapping 003-up runs for the same interface.
lock_base_dir="${OMR_TRACKER_LOCK_DIR:-/var/run/omr-tracker}"
lock_iface="$(printf '%s' "${OMR_TRACKER_INTERFACE:-global}" | tr -c 'A-Za-z0-9_.-' '_')"
lock_dir="${lock_base_dir}/003-up.${lock_iface}.lock"
# A run can't legitimately take this long: past it the pid in the lock was
# recycled by an unrelated process and the lock is stale.
lock_max_age=600

mkdir -p "$lock_base_dir" >/dev/null 2>&1

_acquire_003_up_lock() {
	mkdir "$lock_dir" 2>/dev/null || return 1
	printf '%s\n' "$$" >"$lock_dir/pid"
	date +%s >"$lock_dir/ts" 2>/dev/null
	return 0
}

if ! _acquire_003_up_lock; then
	lock_stale=false
	lock_pid="$(cat "$lock_dir/pid" 2>/dev/null)"
	lock_ts="$(cat "$lock_dir/ts" 2>/dev/null)"
	case "$lock_ts" in
		''|*[!0-9]*) lock_ts="" ;;
	esac
	if [ -z "$lock_ts" ]; then
		# Holder died before writing the timestamp (e.g. killed during a config
		# re-apply): nothing can age the lock safely.
		lock_stale=true
	elif [ "$(($(date +%s) - lock_ts))" -ge "$lock_max_age" ]; then
		lock_stale=true
	elif [ -z "$lock_pid" ]; then
		lock_stale=true
	elif ! kill -0 "$lock_pid" 2>/dev/null; then
		lock_stale=true
	fi
	if [ "$lock_stale" = true ]; then
		_log "Removing stale 003-up lock on ${OMR_TRACKER_INTERFACE:-global}"
		rm -rf "$lock_dir" >/dev/null 2>&1
		if ! _acquire_003_up_lock; then
			_log "Skip overlapping 003-up run on ${OMR_TRACKER_INTERFACE:-global}"
			exit 0
		fi
	else
		_log "Skip overlapping 003-up run on ${OMR_TRACKER_INTERFACE:-global}"
		exit 0
	fi
fi

cleanup_003_up_lock() {
	rm -rf "$lock_dir" >/dev/null 2>&1
}
trap cleanup_003_up_lock EXIT INT TERM


#if [ -n "$RANDOM" ]; then
#	sleep `expr $RANDOM % 10`
#else
#	sleep `awk 'BEGIN{srand();print int(rand()*9)}'`
#fi


# Get the current multipath status
multipath_status="off"
_omr_uci_get_var _globals_multipath network.globals.multipath
if [ -e "/sys/class/net/$OMR_TRACKER_DEVICE" ] && [ "$_globals_multipath" = "enable" ]; then
	case "$(multipath "$OMR_TRACKER_DEVICE")" in
		*default*)      multipath_status="on"       ;;
		*backup*)       multipath_status="backup"   ;;
		*handover*)     multipath_status="handover" ;;
	esac
#	if [ "$(multipath -v $OMR_TRACKER_DEVICE)" = "NOK" ] && [ "$multipath_status" != "off" ]; then
#		_log "Incorrect MPTCP endpoint configuration, fixing..."
#		multipath off >/dev/null 2>&1
#		multipath ${multipath_status} >/dev/null 2>&1
#	fi
fi

# One clock read for the whole run
_omr_now=$(date +%s)

default_gw=$(ip route get 1.1.1.1 2>/dev/null | awk '/via/ {print $3}')
[ -z "$default_gw" ] && default_gw=$(ip route show default metric 0 | awk '/default/ {print $3}')
# Only compared against the interface's IPv6 gateway below: skip the two
# lookups when the interface has none
default_gw6=""
if [ -n "$OMR_TRACKER_DEVICE_GATEWAY6" ]; then
	default_gw6=$(ip -6 route get 2606:4700:4700::1111 2>/dev/null | awk '/via/ {print $3}')
	[ -z "$default_gw6" ] && default_gw6=$(ip -6 route show default metric 0 | awk '/default/ {print $3}')
fi
#current_interface_gw=$(uci -q get "network.$OMR_TRACKER_INTERFACE.gateway")

# The main-table default route at metric 1, read once per run: both the
# master and the non-master balancing blocks check whether the tracked
# device is already one of its nexthops.
_omr_def_m1_loaded=""
_omr_default_m1_has_device() {
	if [ -z "$_omr_def_m1_loaded" ]; then
		_omr_def_m1="$(ip route show default metric 1 2>/dev/null)"
		_omr_def_m1_loaded=1
	fi
	case "$_omr_def_m1" in
		*"$1"*) return 0 ;;
	esac
	return 1
}

# debug is set by common-post-tracking.sh

initcwrwnd=""
if _omr_if_up "$OMR_TRACKER_INTERFACE"; then interface_up="true"; else interface_up="false"; fi

_omr_uci_get_var _intf_state "openmptcprouter.$OMR_TRACKER_INTERFACE.state"
if [ "$_intf_state" != "up" ]; then
	uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.state='up'
#	uci -q commit openmptcprouter
fi


if [ "$OMR_TRACKER_INTERFACE" = "glorytun" ] || [ "$OMR_TRACKER_INTERFACE" = "omrvpn" ] || [ "$OMR_TRACKER_INTERFACE" = "omr6in4" ]; then
	if [ "$(_omr_uci_get network.omrvpn.disabled)" = "1" ]; then
		_log "VPS/tunnel disabled by user, ignore $OMR_TRACKER_INTERFACE up event"
		exit 0
	fi
	if [ "$OMR_TRACKER_INTERFACE" = "omrvpn" ]; then
		uci -q set openmptcprouter.omr.vpn='up'
	fi
	# Tunnel is up again, reset the Glorytun UDP outage state
	rm -f /tmp/omr-tracker-gtudp-error-since /tmp/omr-tracker-gtudp-outage-start /tmp/omr-tracker-gtudp-holddown
	if [ "$(uci -q get openmptcprouter.settings.shadowsocksudp)" = "1" ] && [ "$(uci -q get shadowsocks-libev.sss0.disabled)" != "1" ] && [ -n "$(uci -q get shadowsocks-libev.sss0)" ] && [ "$(uci -q get shadowsocks-libev.ss_rules.redir_udp)" = "hi1" ]; then
		_log "Tunnel up disable use of ShadowSocks for UDP"
		uci -q delete shadowsocks-libev.ss_rules.redir_udp
		if /etc/init.d/shadowsocks-libev rules_exist ; then
			/etc/init.d/shadowsocks-libev rules_down >/dev/null 2>&1
			/etc/init.d/shadowsocks-libev rules_up >/dev/null 2>&1
		fi
	fi
	if { [ "$default_gw" != "$OMR_TRACKER_DEVICE_GATEWAY" ] || [ "$default_gw" = "" ]; } && [ "$OMR_TRACKER_DEVICE_GATEWAY" != "" ]; then
		[ "$debug" = "true" ] && _log "Default gw : $default_gw - Current route: $(ip r)"
		if [ "$(uci -q get openvpn.omr2.enabled)" != "1" ]; then
			_log "Tunnel up : Replace default route by $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE (was $default_gw)"
			ip route replace default scope global via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE $initcwrwnd >/dev/null 2>&1
		else
			_log "Tunnel up : Replace default route by load balancing to $OMR_TRACKER_DEVICE_GATEWAY"
			set_vpn_balancing_routes "$OMR_TRACKER_DEVICE_GATEWAY"
		fi
		if [ "$(pgrep -f openmptcprouter-vps)" = "" ]; then
			/etc/init.d/openmptcprouter-vps restart >/dev/null 2>&1 &
		fi
		[ -n "$(uci -q get shadowsocks-libev.sss0)" ] && [ "$(uci -q get shadowsocks-libev.sss0.disabled)" != "1" ] && conntrack -D -p udp >/dev/null 2>&1
		[ "$debug" = "true" ] && _log "New route: $(ip r)"
	fi

	# Set VPN MTU
	# Not for mqvpn: it negotiates and dynamically re-applies its own tun MTU
	# from the actual QUIC/MASQUE datagram budget (mqvpn_client.c
	# cb_dgram_mss_updated -> cbs.mtu_updated -> mqvpn_tun_set_mtu). A static
	# UCI mtu or omr-mtu's raw path-MTU probe below knows nothing about that
	# per-datagram framing overhead, so it can set a wrong value; worse, an
	# external `ip link set ... mtu` here desyncs mqvpn's own
	# last_notified_mtu tracking from the interface's real state, silencing
	# further mqvpn-side corrections until the next reconnect (live-diagnosed
	# 2026-08-27 as the cause of large UDP through mqvpn getting silently
	# dropped with no signal back to the LAN client).
	_omr_uci_get_var _vpn_lc "openmptcprouter.$OMR_TRACKER_INTERFACE.lc"
	if [ -n "$OMR_TRACKER_LATENCY" ] && [ -n "$OMR_TRACKER_INTERFACE" ] && [ "$(_omr_uci_get openmptcprouter.settings.vpn)" != "mqvpn" ] && { [ -z "$_vpn_lc" ] || [ $((_omr_now - ${_vpn_lc:-0})) -gt 3600 ]; }; then
		#_log "Set VPN MTU"
		serverip=$(uci -q get shadowsocks-libev.sss0.server || uci -q get shadowsocks-rust.sss0.server || uci -q get v2ray.omrout.s_vless_address)
		if [ -n "$serverip" ]; then
			_omr_resolve_var serverip_resolved "-4" "$serverip"
			if [ -n "$serverip_resolved" ] && [ "$serverip_resolved" != "192.168.1.3" ] && [ "$serverip_resolved" != "127.0.0.1" ]; then
				serverip="$serverip_resolved"
			else
				serverip=""
			fi
		fi
		uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE="interface"
		# Measured latency is volatile state, not configuration (see omr-state.sh)
		omr_state_set openmptcprouter "$OMR_TRACKER_INTERFACE" latency "$OMR_TRACKER_LATENCY"
		#if [ "$(uci -q get glorytun.vpn.enable)" != "1" ] || [ "$(uci -q get glorytun-udp.vpn.enable)" != "1" ]; then
			OMR_NETWORK_DEVICE=$(find_network_device ${OMR_TRACKER_INTERFACE})
			#_log "OMR_NETWORK_DEVICE: $OMR_NETWORK_DEVICE for $OMR_TRACKER_DEVICE - $OMR_TRACKER_INTERFACE"
			if [ -n "$OMR_NETWORK_DEVICE" ] && [ -n "$(_omr_uci_get network.$OMR_NETWORK_DEVICE.mtu)" ] && [ -n "$OMR_TRACKER_INTERFACE" ]; then
				mtu=$(_omr_uci_get network.${OMR_NETWORK_DEVICE}.mtu)
				[ -z "$mtu" ] && mtu=$(_omr_uci_get network.${OMR_NETWORK_INTERFACE}.mtu)
				uci -q set openmptcprouter.${OMR_TRACKER_INTERFACE}.mtu=$mtu
				[ -n "$mtu" ] && [ "$(ip --json link show dev $OMR_TRACKER_DEVICE | jsonfilter -e '@[0].mtu' | tr -d '\n')" != "$mtu" ] && ip link set dev $OMR_TRACKER_DEVICE mtu $mtu > /dev/null 2>&1
				uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.lc="$_omr_now"
			elif [ -z "$(_omr_uci_get openmptcprouter.${OMR_TRACKER_INTERFACE}.mtu)" ] && [ -n "$OMR_TRACKER_DEVICE_IP" ] && [ -n "$OMR_TRACKER_DEVICE" ]; then
				# IPv4 probe: an IPv6 server address here would make
				# omr-mtu ping the wrong family and report nothing
				_mtu_target="1.1.1.1"
				case "$serverip" in
					''|127.0.0.1|*:*) ;;
					*) _mtu_target="$serverip" ;;
				esac
				mtu=$(omr-mtu $OMR_TRACKER_DEVICE_IP $_mtu_target)
				case "$mtu" in ''|*[!0-9]*) mtu="" ;; esac
				[ -n "$mtu" ] && {
					uci -q set openmptcprouter.${OMR_TRACKER_INTERFACE}.mtu=$mtu
					# Changing the MTU resets the carrier on several NIC
					# drivers, so only touch the link when it differs
					[ "$(ip --json link show dev $OMR_TRACKER_DEVICE | jsonfilter -q -e '@[0].mtu' | tr -d '\n')" != "$mtu" ] && \
						ip link set dev $OMR_TRACKER_DEVICE mtu $mtu > /dev/null 2>&1
					uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.lc="$_omr_now"
				}
			else
				uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.lc="$_omr_now"
			fi
		#else
		#	uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.lc=$(date +"%s")
		#fi
	fi
	[ -n "$(uci -q changes openmptcprouter)" ] && uci -q commit openmptcprouter
	nbserver=0
	piholeenabled=0
	if [ "$(_omr_uci_get openmptcprouter.settings.pihole_auto_conf)" != "0" ]; then
		config_load openmptcprouter
		config_foreach enable_pihole server
		#config_foreach delete_server_default_route server
		[ "$nbserver" = "$piholeenabled" ] && /etc/init.d/openmptcprouter-vps set_pihole >/dev/null 2>&1
	fi
	#ubus call network reload
	exit 0
fi

if [ -n "$OMR_TRACKER_INTERFACE" ] && [ "$(_omr_uci_get openmptcprouter.$OMR_TRACKER_INTERFACE.vpn)" = "1" ]; then
	if [ "$(_omr_uci_get openmptcprouter.$OMR_TRACKER_INTERFACE.state)" != "up" ]; then
		uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.state='up'
		[ -n "$(uci -q changes openmptcprouter)" ] && uci -q commit openmptcprouter
	fi
	exit 0
fi
# Only touch uci when there is something to remove: a blind delete costs a
# fork on every cycle and invalidates the cached config for nothing
_omr_uci_get_var _restart_intf "openmptcprouter.$OMR_TRACKER_INTERFACE.restart_intf" && uci -q del openmptcprouter.$OMR_TRACKER_INTERFACE.restart_intf

if [ "$OMR_TRACKER_PREV_STATUS" != "" ] && [ "$OMR_TRACKER_PREV_STATUS" != "$OMR_TRACKER_STATUS" ] && [ -n "$OMR_TRACKER_INTERFACE" ]; then
	_log "$OMR_TRACKER_INTERFACE ($OMR_TRACKER_DEVICE) switched up"
	mail_alert="$(uci -q get omr-tracker.$OMR_TRACKER_INTERFACE.mail_alert)"
	[ -z "$mail_alert" ] && mail_alert="$(uci -q get omr-tracker.defaults.mail_alert)"
	mail_to="$(uci -q get mail.default.to | tr -d '\r\n')"
	case "$mail_to" in
		-*|*[[:space:]]*) mail_to="" ;;
	esac
	[ "$mail_alert" = "1" ] && [ -n "$mail_to" ] && {
		OMR_SYSNAME="$(uci -q get system.@system[0].hostname)"
		if [ "$(uci -q get omr-tracker.defaults.mail_up_subject)" != "" ] && [ "$(uci -q get omr-tracker.defaults.mail_up_message)" != "" ]; then
			mail_subject="$(uci -q get omr-tracker.defaults.mail_up_subject)"
			mail_subject=`echo $mail_subject | sed -e "s/%SYSNAME%/$OMR_SYSNAME/g" -e "s/%INTERFACE%/$OMR_TRACKER_INTERFACE/g" -e "s/%DEVICE%/$OMR_TRACKER_DEVICE/g" -e "s/%MESSAGE%/$OMR_TRACKER_STATUS_MSG/g"`
			mail_subject="$(printf '%s' "$mail_subject" | tr -d '\r\n')"
			mail_message="$(uci -q get omr-tracker.defaults.mail_up_message)"
			mail_message=`echo $mail_message | sed -e "s/%SYSNAME%/$OMR_SYSNAME/g" -e "s/%INTERFACE%/$OMR_TRACKER_INTERFACE/g" -e "s/%DEVICE%/$OMR_TRACKER_DEVICE/g" -e "s/%MESSAGE%/$OMR_TRACKER_STATUS_MSG/g"`
			printf 'Subject: %s\n\n%s\n' "$mail_subject" "$mail_message" | sendmail "$mail_to"
		else
			mail_subject="$(printf '%s' "$OMR_SYSNAME: $OMR_TRACKER_INTERFACE ($OMR_TRACKER_DEVICE) is up" | tr -d '\r\n')"
			printf 'Subject: %s\n\nDetected that connection %s (%s) is up again.\n' "$mail_subject" "$OMR_TRACKER_INTERFACE" "$OMR_TRACKER_DEVICE" | sendmail "$mail_to"
		fi
	}
	script_alert_up="$(uci -q get omr-tracker.$OMR_TRACKER_INTERFACE.script_alert_up)"
	[ -n "$script_alert_up" ] && eval $script_alert_up
	env -i ACTION="connecting" INTERFACE="$OMR_TRACKER_INTERFACE" DEVICE="$OMR_TRACKER_DEVICE" /sbin/hotplug-call iface
fi
if [ -n "$OMR_TRACKER_INTERFACE" ] && [ "$(_omr_uci_get openmptcprouter.$OMR_TRACKER_INTERFACE.state)" != "up" ]; then
	uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.state='up'
	dns_flush
fi

if [ -n "$OMR_TRACKER_INTERFACE" ]; then
	_omr_uci_get_var multipath_config "openmptcprouter.$OMR_TRACKER_INTERFACE.multipath"
	_omr_uci_get_var _multipath_setting "network.$OMR_TRACKER_INTERFACE.multipath"
	_omr_uci_get_var _multipathvpn "openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn"
	# openmptcprouter.<iface>.multipath is the *effective* mode, network.<iface>.multipath
	# the one the user configured. OMR itself only ever moves the effective copy
	# between "on" and "master" (dynamic master election in 021-latencies) or parks
	# it at "off" for MPTCP over VPN and for a disabled interface. Any other
	# difference means the effective copy is stale, and since it wins below the
	# interface would keep being forced back to that stale mode forever: a WAN once
	# set to "backup" stayed backup whatever the wizard/MPTCP page was set to
	# afterwards, because LuCI drops network.<iface>.multipath when the selected
	# value equals the option default and mptcp's init then restored the old
	# effective value into it (discussion #4368).
	_omr_uci_get_var _multipath_disabled "network.$OMR_TRACKER_INTERFACE.disabled"
	if [ -n "$_multipath_setting" ] && [ "$_multipath_setting" != "$multipath_config" ] && \
		[ "$_multipathvpn" != "1" ] && [ "$_multipath_disabled" != "1" ]; then
		case "${multipath_config}/${_multipath_setting}" in
			on/master|master/on) ;;
			*)
				_log "Multipath mode of $OMR_TRACKER_INTERFACE is $multipath_config but configured as $_multipath_setting, resync"
				uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.multipath="$_multipath_setting"
				multipath_config="$_multipath_setting"
			;;
		esac
	fi
	[ -z "$multipath_config" ] && multipath_config="${_multipath_setting:-off}"
	[ "$_multipathvpn" = "1" ] && {
		_omr_uci_get_var _mptcpovervpn openmptcprouter.settings.mptcpovervpn
		[ "$_mptcpovervpn" = "openvpn" ] && _omr_uci_get_var multipath_config_route "openmptcprouter.ovpn${OMR_TRACKER_INTERFACE}.multipath" "off"
		[ "$_mptcpovervpn" = "wireguard" ] && _omr_uci_get_var multipath_config_route "openmptcprouter.wg${OMR_TRACKER_INTERFACE}.multipath" "off"
	}
fi

_omr_uci_get_var master_setting openmptcprouter.settings.master
_omr_uci_get_var defaultgw_setting openmptcprouter.settings.defaultgw
_omr_uci_get_var omrvpn_intf network.omrvpn.device "tun0"
[ -z "$omrvpn_intf" ] && _omr_uci_get_var omrvpn_intf network.omrvpn.ifname "tun0"
if [ "$multipath_config" = "master" ]; then
	if [ "$master_setting" != "balancing" ]; then
		if { [ "$default_gw" != "$OMR_TRACKER_DEVICE_GATEWAY" ] || [ "$default_gw" = "" ]; } && [ "$OMR_TRACKER_DEVICE_GATEWAY" != "" ]; then
			if [ -n "$omrvpn_intf" ] && [ "$(ip route show default metric 0 | grep $omrvpn_intf)" = "" ] && [ "$defaultgw_setting" != "0" ]; then
				_log "Master up : Replace default route by $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE"
				ip route replace default scope global metric 1 via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE $initcwrwnd >/dev/null 2>&1
			fi
			config_load openmptcprouter
			#if [ "$master_setting" = "balancing" ]; then
			#	config_foreach set_server_all_routes server
			if [ "$master_setting" != "failover" ]; then
				config_foreach set_server_default_route server
				#config_foreach set_server_default_route6 server
			fi
			ip route flush cache >/dev/null 2>&1
		fi
		if { [ "$default_gw6" != "$OMR_TRACKER_DEVICE_GATEWAY6" ] || [ "$default_gw6" = "" ]; } && [ "$OMR_TRACKER_DEVICE_GATEWAY6" != "" ]; then
			if [ -n "$omrvpn_intf" ] && [ "$(ip route show default | awk '/default/ {print $5}' | grep $omrvpn_intf)" = "" ] && [ "$defaultgw_setting" != "0" ]; then
				_log "Master up : Replace default route by $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE"
				ip -6 route replace default scope global nexthop via $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE >/dev/null 2>&1
			fi
			config_load openmptcprouter
			#if [ "$master_setting" = "balancing" ]; then
			#	config_foreach set_server_all_routes server
			if [ "$master_setting" != "failover" ]; then
				#config_foreach set_server_default_route server
				config_foreach set_server_default_route6 server
			fi
			ip -6 route flush cache >/dev/null 2>&1
		fi
	fi
	if [ "$master_setting" = "balancing" ]; then
		if { { [ -n "$OMR_TRACKER_DEVICE_IP" ] && ! _omr_default_m1_has_device "$OMR_TRACKER_DEVICE"; } || { [ -n "$OMR_TRACKER_DEVICE_IP6" ] && [ "$(ip -6 route show default metric 1 | grep "$OMR_TRACKER_DEVICE")" = "" ]; }; } && [ "$defaultgw_setting" != "0" ]; then
			if [ -n "$omrvpn_intf" ] && [ -n "$OMR_TRACKER_DEVICE_IP" ]; then
				routesbalancing=""
				routesbalancingbackup=""
				nbintf=0
				nbintfb=0
				config_load network
				config_foreach set_route_balancing interface
				[ -n "$routesbalancing" ] && ! _default_route_matches 1 "$routesbalancing" "$nbintf" false && {
					_log "Change in routes, set ip route replace default scope global $routesbalancing (omrvpn_intf: $omrvpn_intf)"
					[ "$debug" = "true" ] && _log "Current route: $(ip r)"
					ip route replace default scope global metric 1 $routesbalancing >/dev/null 2>&1
					_omr_def_m1_loaded=""
					[ "$debug" = "true" ] && _log "New route: $(ip r)"
				}
				[ -n "$routesbalancingbackup" ] && ! _default_route_matches 999 "$routesbalancingbackup" "$nbintfb" false && {
					_log "Set backup ip route replace default scope global metric 999 $routesbalancingbackup"
					ip route replace default scope global metric 999 $routesbalancingbackup >/dev/null 2>&1
				}
			fi
			if [ -n "$omrvpn_intf" ] && [ -n "$OMR_TRACKER_DEVICE_IP6" ] && [ "$(ip -6 route show default metric 1 | tr -d '\t' | tr -d '\n' | sed 's/ *$//')" != "default via $routesbalancing6" ]; then
				routesbalancing6=""
				routesbalancingbackup6=""
				nbintf6=0
				nbintfb6=0
				config_load network
				config_foreach set_route_balancing6 interface
				[ -n "$routesbalancing6" ] && [ "$(ip -6 r show default metric 1 | grep omr6in4)" = "" ] && ! _default_route_matches 1 "$routesbalancing6" "$nbintf6" true && {
					_log "Set ip -6 route replace default scope global metric 1 $routesbalancing6"
					[ "$debug" = "true" ] && _log "Current route: $(ip -6 r)"
					ip -6 route replace default scope global metric 1 $routesbalancing6 >/dev/null 2>&1
					[ "$debug" = "true" ] && _log "New route: $(ip -6 r)"
				}
				[ -n "$routesbalancingbackup6" ] && ! _default_route_matches 999 "$routesbalancingbackup6" "$nbintfb6" true && {
					_log "Set backup ip -6 route replace default scope global $routesbalancingbackup6"
					ip -6 route replace default scope global metric 999 $routesbalancingbackup6 >/dev/null 2>&1
				}
			fi
			#ip route flush cache >/dev/null 2>&1
			#ip -6 route flush cache >/dev/null 2>&1
		fi
	fi
	if [ -n "$OMR_TRACKER_DEVICE_GATEWAY" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ "$(ip r show table 991337)" != "default via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE " ]; then
		ip route replace default via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE table 991337 $initcwrwnd >/dev/null 2>&1
		#ip route flush cache >/dev/null 2>&1
	fi
	if [ -n "$OMR_TRACKER_DEVICE_GATEWAY6" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ "$(ip -6 r show table 6991337)" != "default via $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE " ]; then
		ip -6 route replace default via $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE table 6991337 $initcwrwnd >/dev/null 2>&1
		#ip -6 route flush cache >/dev/null 2>&1
	fi
	lc_jitter=$((10 + RANDOM % 10))
	_omr_uci_get_var _lc "openmptcprouter.$OMR_TRACKER_INTERFACE.lc"
	if { [ -n "$OMR_TRACKER_INTERFACE" ] && [ -z "$_lc" ]; } || [ $((_omr_now + lc_jitter - ${_lc:-0})) -gt 3600 ] || _omr_uci_has "get_config='1'" || _omr_uci_has "admin_error='1'"; then
		[ -z "$(pgrep -f openmptcprouter-vps)" ] && {
			/etc/init.d/openmptcprouter-vps restart >/dev/null 2>&1 &
			uci -q set openmptcprouter."$OMR_TRACKER_INTERFACE".lc="$_omr_now"
			#uci -q commit openmptcprouter.$OMR_TRACKER_INTERFACE
		}
	fi
	multipath_config="on"
fi

if [ "$master_setting" = "balancing" ] && { [ "$multipath_config" = "on" ] || [ "$multipath_config" = "backup" ]; } && [ "$defaultgw_setting" != "0" ]; then
	if [ -n "$omrvpn_intf" ] && [ -n "$OMR_TRACKER_DEVICE_IP" ] && ! _omr_default_m1_has_device "$OMR_TRACKER_DEVICE"; then
		routesbalancing=""
		routesbalancingbackup=""
		nbintf=0
		nbintfb=0
		config_load network
		config_foreach set_route_balancing interface
		# Compare the current route against what we would install instead of
		# grepping it for the tracked device: a backup interface is never in
		# the metric-1 route, so the device grep replaced and logged an
		# already correct route on every tracker cycle (issue #4358).
		[ -n "$routesbalancing" ] && ! _default_route_matches 1 "$routesbalancing" "$nbintf" false && {
			_log "Change in routes (non-master), set ip route replace default scope global metric 1 $routesbalancing"
			ip route replace default scope global metric 1 $routesbalancing >/dev/null 2>&1
		}
		[ -n "$routesbalancingbackup" ] && ! _default_route_matches 999 "$routesbalancingbackup" "$nbintfb" false && {
			_log "Set backup ip route replace default scope global metric 999 $routesbalancingbackup"
			ip route replace default scope global metric 999 $routesbalancingbackup >/dev/null 2>&1
		}
	fi
	# Non-master (on/backup) WAN recovering never resynced the VPS-side
	# port-forward/redirect state (only the master WAN's own up-event did,
	# incidentally, via the block above) - mirror that lc-staleness-gated
	# resync here so a secondary WAN flap also repairs port-forwarding.
	lc_jitter=$((10 + RANDOM % 10))
	_omr_uci_get_var _lc "openmptcprouter.$OMR_TRACKER_INTERFACE.lc"
	if { [ -n "$OMR_TRACKER_INTERFACE" ] && [ -z "$_lc" ]; } || [ $((_omr_now + lc_jitter - ${_lc:-0})) -gt 3600 ] || _omr_uci_has "get_config='1'" || _omr_uci_has "admin_error='1'"; then
		[ -z "$(pgrep -f openmptcprouter-vps)" ] && {
			/etc/init.d/openmptcprouter-vps restart >/dev/null 2>&1 &
			uci -q set openmptcprouter."$OMR_TRACKER_INTERFACE".lc="$_omr_now"
		}
	fi
fi

_omr_uci_get_var intf_metric "network.$OMR_TRACKER_INTERFACE.metric"
if [ "$master_setting" = "balancing" ] && [ -n "$OMR_TRACKER_DEVICE_IP" ]; then
	config_load openmptcprouter
	config_foreach set_server_all_routes server
fi
if [ "$master_setting" = "balancing" ] && [ -n "$OMR_TRACKER_DEVICE_IP6" ]; then
	config_load openmptcprouter
	config_foreach set_server_all_routes6 server
fi
if [ -n "$OMR_TRACKER_DEVICE_IP" ] && [ -n "$OMR_TRACKER_DEVICE_GATEWAY" ]; then
	config_load openmptcprouter
	if [ "$master_setting" != "balancing" ] && [ "$master_setting" != "failover" ]; then
		config_foreach set_server_route server
	fi
	_omr_dev_routes=""
	[ -n "$OMR_TRACKER_DEVICE" ] && _omr_dev_routes="$(ip r show dev $OMR_TRACKER_DEVICE 2>/dev/null)"
	case "$_omr_dev_routes" in *default*) _omr_dev_has_default=1 ;; *) _omr_dev_has_default="" ;; esac
	if [ "$defaultgw_setting" != "0" ] && [ -n "$OMR_TRACKER_DEVICE_GATEWAY" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ -z "$_omr_dev_has_default" ] && [ -n "$OMR_TRACKER_INTERFACE" ] && [ "$intf_metric" != "" ]; then
		_log "Interface route not yet set, set route ip r add default via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE metric $intf_metric"
		ip r add default via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE metric $intf_metric >/dev/null 2>&1
		ip route flush cache >/dev/null 2>&1
	fi
fi
if [ -n "$OMR_TRACKER_DEVICE_IP6" ] && [ -n "$OMR_TRACKER_DEVICE_GATEWAY6" ]; then
	config_load openmptcprouter
	if [ "$master_setting" != "balancing" ] && [ "$master_setting" != "failover" ]; then
		config_foreach set_server_route6 server
	fi
	if [ "$defaultgw_setting" != "0" ] && [ -n "$OMR_TRACKER_DEVICE_GATEWAY6" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ "$(ip -6 r show dev $OMR_TRACKER_DEVICE | grep default)" = "" ] && [ -n "$OMR_TRACKER_INTERFACE" ] && [ "$intf_metric" != "" ]; then
		_log "Interface route not yet set, set route ip -6 r add default via $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE metric 6$intf_metric"
		ip -6 r replace default via $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE metric 6$intf_metric >/dev/null 2>&1
		ip -6 route flush cache >/dev/null 2>&1
	fi
fi

if [ -n "$OMR_TRACKER_INTERFACE" ] && { [ "$multipath_config" = "on" ] || [ "$multipath_config" = "backup" ]; }; then
	# Make sure the openmptcprouter config exists before writing to it
	# (was a full "uci show | grep" of every package on each cycle)
	[ -e "${UCI_CONFIG_DIR:-/etc/config}/openmptcprouter" ] || touch "${UCI_CONFIG_DIR:-/etc/config}/openmptcprouter" 2>/dev/null
fi
# One sysctl for both the upstream (net.mptcp.enabled) and legacy
# (net.mptcp.mptcp_enabled) keys: -e skips the one the kernel doesn't have
_mptcp_enabled="$(sysctl -qen net.mptcp.enabled net.mptcp.mptcp_enabled 2>/dev/null)"
case "$_mptcp_enabled" in
	*1*) _mptcp_enabled=1 ;;
	*) _mptcp_enabled="" ;;
esac
if [ -n "$_mptcp_enabled" ]; then
	_omr_uci_get_var _multipathvpn "openmptcprouter.$OMR_TRACKER_INTERFACE.multipathvpn"
	_omr_uci_get_var _force_multipath network.globals.mptcp_force_multipath
	_omr_uci_get_var _force_link "network.$OMR_TRACKER_INTERFACE.force_link"
	[ "$_multipathvpn" != "1" ] && [ "$_force_multipath" != "0" ] && [ "$_globals_multipath" = "enable" ] && {
		if [ "$OMR_TRACKER_PREV_STATUS" != "" ] && [ "$OMR_TRACKER_PREV_STATUS" != "$OMR_TRACKER_STATUS" ]; then
			if [ -n "$OMR_TRACKER_DEVICE" ] && [ "$_force_link" != "0" ]; then
				_log "Status change, reload MPTCP config for $OMR_TRACKER_DEVICE"
				/etc/init.d/mptcp reload "$OMR_TRACKER_DEVICE"
			fi
		fi
		_omr_uci_get_var _local_ipv4 "openmptcprouter.$OMR_TRACKER_INTERFACE.local_ipv4"
		_omr_uci_get_var _local_ipv6 "openmptcprouter.$OMR_TRACKER_INTERFACE.local_ipv6"
		if [ "$multipath_status" = "$multipath_config" ] && { [ "$_local_ipv4" != "$OMR_TRACKER_DEVICE_IP" ] || [ "$_local_ipv6" != "$OMR_TRACKER_DEVICE_IP6" ]; }; then
			_log "Local IP changed for $OMR_TRACKER_DEVICE ($OMR_TRACKER_INTERFACE) reload Multipath"
			if [ -n "$OMR_TRACKER_DEVICE" ] && [ "$_force_link" != "0" ]; then
				_log "Reload MPTCP config for $OMR_TRACKER_DEVICE"
				/etc/init.d/mptcp reload "$OMR_TRACKER_DEVICE"
			fi
			uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.local_ipv4="$OMR_TRACKER_DEVICE_IP"
			uci -q set openmptcprouter.$OMR_TRACKER_INTERFACE.local_ipv6="$OMR_TRACKER_DEVICE_IP6"
		elif [ "$multipath_status" != "$multipath_config" ]; then
			_log "Multipath $OMR_TRACKER_DEVICE ($OMR_TRACKER_INTERFACE) switched to $multipath_config (from $multipath_status)"
			# Same explicit endpoint id as mptcp's init script (network.<iface>.metric):
			# without it the kernel auto-assigns a new id every time the endpoint is
			# recreated here, so the id a WAN is known by drifts upwards on every
			# status change and the VPS side can no longer pin traffic to a WAN by
			# the subflow remote_id (see "multipath -h", mptcp-dscp/weight sync).
			_omr_uci_get_var _multipath_id "network.$OMR_TRACKER_INTERFACE.metric"
			multipath "$OMR_TRACKER_DEVICE" "$multipath_config" "$_multipath_id"
			if [ -n "$OMR_TRACKER_DEVICE" ] && [ "$_force_link" != "0" ]; then
				/etc/init.d/mptcp reload "$OMR_TRACKER_DEVICE"
			fi
		fi
	}
fi
[ -n "$(uci -q changes openmptcprouter)" ] && uci -q commit openmptcprouter

#[ -n "$OMR_TRACKER_DEVICE" ] && OMR_TRACKER_PREV_DEVICE="$OMR_TRACKER_DEVICE"

#ubus call network reload
exit 0
