#!/bin/sh
#
# Copyright (C) 2018-2026 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 check if MPTCP status is correct on interface and if modems are correctly set on z8102ax

# Set default multipath status. Not without a device: "multipath" with an
# empty first argument lists the mode of every network device instead (a
# multipath run per device, some 250 processes on each cycle while the
# tunnel is down) and changes nothing.
[ "$OMR_TRACKER_INTERFACE" = "omrvpn" ] && [ -n "$OMR_TRACKER_DEVICE" ] && multipath "$OMR_TRACKER_DEVICE" off >/dev/null 2>&1
[ "$OMR_TRACKER_INTERFACE" = "omr6in4" ] && [ -n "$OMR_TRACKER_DEVICE" ] && multipath "$OMR_TRACKER_DEVICE" off >/dev/null 2>&1

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

if [ -n "$OMR_TRACKER_INTERFACE" ] && [ -n "$OMR_TRACKER_DEVICE" ] && [ "$OMR_TRACKER_INTERFACE" != "omrvpn" ] && [ "$OMR_TRACKER_INTERFACE" != "omr6in4" ]; then
	# Plain uci gets on purpose: this script reads only a couple of options,
	# so building the library's config map (see common-post-tracking.sh)
	# would cost more than the forks it saves
	if [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.disabled)" = "1" ]; then
		_log "Disable MPTCP & Tracker on the disabled interface $OMR_TRACKER_INTERFACE ($OMR_TRACKER_DEVICE)"
		/etc/init.d/mptcp reload "$OMR_TRACKER_DEVICE" >/dev/null 2>&1
		# Detached and out of this tracker's cgroup: the restart stops this
		# tracker, which waits for this script, and procd kills what is left
		# in its cgroup
		_omr_detach /etc/init.d/omr-tracker restart
		exit 0
	fi
	# The device's name anywhere in the table, as grep did, without the
	# grep and its subshell: this runs on every post-tracking cycle
	_table_has_device() {
		case "$1" in
			*"$OMR_TRACKER_DEVICE"*) return 0 ;;
		esac
		return 1
	}
	_routes_missing() {
		metric="$(uci -q get network.$OMR_TRACKER_INTERFACE.metric)"
		[ -z "$metric" ] || { [ -n "$OMR_TRACKER_DEVICE_IP" ] && ! _table_has_device "$(ip route show table $metric)"; } || { [ -n "$OMR_TRACKER_DEVICE_IP6" ] && ! _table_has_device "$(ip -6 route show table 6${metric})"; }
	}
	# No carrier: the kernel flushed the device's routes on link-down and
	# none can be put back until the link returns -- omr-tracker restores them
	# itself on the carrier's return (_on_carrier_return). Repairing here used
	# to reload MPTCP and restart *every* tracker on each post-tracking run of
	# the outage, bouncing the healthy WANs' trackers along with it.
	_carrier=""
	read -r _carrier 2>/dev/null < "${OMR_SYS_CLASS_NET_DIR:-/sys/class/net}/${OMR_TRACKER_DEVICE}/carrier"
	if [ "$_carrier" = "1" ] && _routes_missing; then
		_log "Routes not correctly set for $OMR_TRACKER_INTERFACE ($OMR_TRACKER_DEVICE table $metric) with IPs $OMR_TRACKER_DEVICE_IP $OMR_TRACKER_DEVICE_IP6"
		/etc/init.d/mptcp reload "$OMR_TRACKER_DEVICE" >/dev/null 2>&1
		if _routes_missing; then
			# Only this interface's tracker, and detached: this script runs
			# inside that tracker, which cannot act on the SIGTERM while it
			# waits for us -- restarting it in the foreground stalled until
			# procd's SIGKILL, 5s later.
			_log "Restart OMR-Tracker for $OMR_TRACKER_INTERFACE"
			( /etc/init.d/omr-tracker restart "$OMR_TRACKER_INTERFACE" >/dev/null 2>&1 </dev/null & )
		else
			_log "Routes restored for $OMR_TRACKER_INTERFACE ($OMR_TRACKER_DEVICE)"
		fi
		exit 0
	fi
fi

# One grep -q per board family rather than a subshell per board name: the
# board never changes, and these ran on every post-tracking cycle
if grep -q -E 'z8102ax|z8802|z8803' /etc/board.json && [ "$(uci -q get network.modem1.proto)" = "modemmanager" ]; then
	if [ -e /sys/devices/platform/soc/11200000.usb/usb1/1-1/1-1.1 ]; then
		uci -q batch <<-EOF
		set network.modem1.device='/sys/devices/platform/soc/11200000.usb/usb1/1-1/1-1.1'
		set network.modem2.device='/sys/devices/platform/soc/11200000.usb/usb1/1-1/1-1.2'
		EOF
	elif [ -e /sys/devices/platform/soc/11200000.usb/usb2/2-1/2-1.1 ]; then
		uci -q batch <<-EOF
		set network.modem1.device='/sys/devices/platform/soc/11200000.usb/usb2/2-1/2-1.1'
		set network.modem2.device='/sys/devices/platform/soc/11200000.usb/usb2/2-1/2-1.2'
		EOF
	fi
	[ -n "$(uci -q changes network)" ] && uci -q commit network
fi
if grep -q z8109ax /etc/board.json && [ "$(uci -q get network.modem1.proto)" = "modemmanager" ]; then
	if [ -e /sys/devices/platform/soc/11200000.usb/usb1/1-1/1-1.1 ]; then
		uci -q batch <<-EOF
		set network.modem1.device='/sys/devices/platform/soc/11200000.usb/usb1/1-1/1-1.1'
		set network.modem2.device='/sys/devices/platform/soc/11200000.usb/usb1/1-1/1-1.2'
		set network.modem3.device='/sys/devices/platform/soc/11200000.usb/usb1/1-1/1-1.3'
		set network.modem4.device='/sys/devices/platform/soc/11200000.usb/usb1/1-1/1-1.4'
		EOF
	elif [ -e /sys/devices/platform/soc/11200000.usb/usb2/2-1/2-1.1 ]; then
		uci -q batch <<-EOF
		set network.modem1.device='/sys/devices/platform/soc/11200000.usb/usb2/2-1/2-1.1'
		set network.modem2.device='/sys/devices/platform/soc/11200000.usb/usb2/2-1/2-1.2'
		set network.modem3.device='/sys/devices/platform/soc/11200000.usb/usb2/2-1/2-1.3'
		set network.modem4.device='/sys/devices/platform/soc/11200000.usb/usb2/2-1/2-1.4'
		EOF
	fi
	[ -n "$(uci -q changes network)" ] && uci -q commit network
fi

# Force unbound DNS resolution on IPv4 if n IPv6 set
# The minute-rate unbound_lc timestamp lives in uci state (tmpfs): committed
# to /etc/config it was a flash write every 60 s (see omr-state.sh)
_unbound_lc=$(omr_state_get openmptcprouter.settings.unbound_lc)
[ -z "$_unbound_lc" ] && _unbound_lc=$(uci -q get openmptcprouter.settings.unbound_lc)
_unbound_now=$(date +%s)
# The timestamp first: the unbound config is only looked at once a minute
if { [ -z "$_unbound_lc" ] || [ $((_unbound_now - _unbound_lc)) -gt 60 ]; } && [ -n "$(uci -q show unbound)" ]; then
	omr_state_migrate openmptcprouter settings unbound_lc
	omr_state_set openmptcprouter settings unbound_lc "$_unbound_now"
	if [ -n "$(ip -6 r show scope global)" ]; then
		uci -q set unbound.ub_main.protocol='mixed'
	else
		uci -q set unbound.ub_main.protocol='default'
	fi
	[ -n "$(uci -q changes unbound)" ] && {
		uci -q commit unbound
		/etc/init.d/unbound reload
	}
fi