#!/bin/bash
# shellcheck disable=SC1091,SC1090
# vim: set noexpandtab tabstop=4 shiftwidth=4 softtabstop=4 :

[ -n "$1" ] || exit

. /lib/functions.sh
. /usr/lib/unbound/iptools.sh
. /lib/functions/network.sh

# retrieve args
OMR_TRACKER_INTERFACE="$1"
shift

# export vars
export OMR_TRACKER_INTERFACE
export OMR_TRACKER_HOST
export OMR_TRACKER_HOST6
export OMR_TRACKER_TIMEOUT
export OMR_TRACKER_SIZE
export OMR_TRACKER_MAX_TTL
export OMR_TRACKER_LOSS
export OMR_TRACKER_STATUS
export OMR_TRACKER_STATUS_MSG
export OMR_TRACKER_PREV_STATUS
export OMR_TRACKER_DEVICE
export OMR_TRACKER_PREV_DEVICE
export OMR_TRACKER_DEVICE_IP
export OMR_TRACKER_DEVICE_IP6
export OMR_TRACKER_PREV_DEVICE_IP
export OMR_TRACKER_PREV_DEVICE_IP6
export OMR_TRACKER_DEVICE_GATEWAY
export OMR_TRACKER_DEVICE_GATEWAY6
export OMR_TRACKER_IPV6
export OMR_TRACKER_PROTO
export OMR_TRACKER_INTERVAL_TRIES
export OMR_TRACKER_INTERVAL
export OMR_TRACKER_NO_BIND
export OMR_TRACKER_TYPE

#dscp=56   # set DSCP CS7 (56) in outgoing packets

#initial_hosts="$OMR_TRACKER_HOSTS"
#initial_hosts6="$OMR_TRACKER_HOSTS6"
initial_timeout="$OMR_TRACKER_TIMEOUT"
wait_test=${OMR_TRACKER_WAIT_TEST:-0}

# set constants for rto updating
# we've changed the default values of the RFC to K=3 and beta=0.25 instead of K=4 and beta=0.125
# this allows us to lower the gap between rtt and rto when the latency increases quickly as our
# measurements are less frequent than the standard timeout computation of the TCP stack
_init_rto() {
	srtt=
	rttvar=
	rto_init=$(( initial_timeout * 1000 ))
	rto=$rto_init
}

# update rto as explained in rfc6298
# rto    : retransmission timeout.
# rtt    : round trip time
# rttvar : round trip time variance
# srtt   : smoothed round trip time
# alpha  : smoothing coeff for srtt
# beta   : smoothing coeff for rttvar
# K      : coeff to increase rttvar impact on rto computation
_update_rto() {
	if [ -z "$srtt" ]; then
		srtt=$1
		rttvar=$(echo "$(($1 / 2))" | cut -d. -f1)
		#"
	else
		diff=$((srtt - $1))
		rttvar=$(echo "$(((75 * rttvar + 25 * (diff >= 0 ? diff : -diff)) / 100))" | cut -d. -f1)
		srtt=$(echo "$(((75 * srtt + 25 * $1) / 100))" | cut -d. -f1)
	fi
	rto=$((tmp = srtt + 3 * rttvar, tmp > rto_init ? tmp : rto_init))
}

_restart() {
	OMR_TRACKER_HOST="${OMR_TRACKER_HOSTS%% *}"
	OMR_TRACKER_HOST6="${OMR_TRACKER_HOSTS6%% *}"
	[ "$OMR_TRACKER_HOST" = "$OMR_TRACKER_HOSTS" ] || {
		OMR_TRACKER_HOSTS="${OMR_TRACKER_HOSTS#* } $OMR_TRACKER_HOST"
		_init_rto
	}
	[ "$OMR_TRACKER_HOST6" = "$OMR_TRACKER_HOSTS6" ] || {
		OMR_TRACKER_HOSTS6="${OMR_TRACKER_HOSTS6#* } $OMR_TRACKER_HOST6"
		_init_rto
	}
}

_post_tracking() {
	for tracker_bin in /usr/share/omr/post-tracking.d/*; do
		[ -x "$tracker_bin" ] && (
			_log() {
				logger -t "post-tracking-${tracker_bin##*/}" "$*"
			}
			#. "$tracker_bin" 2>&1
			#tmp=$(mktemp)
			#. "$tracker_bin" 2>&1 > "$tmp"
			#trackresult=$(< "$tmp")
			#[ -n "$trackresult" ] && _log $trackresult
			#rm -f "$tmp"
			EVAL_OUTPUT=$(. "$tracker_bin" 2>&1)
			if [ -n "$EVAL_OUTPUT" ]; then
				eval "$EVAL_OUTPUT" >/dev/null 2>&1
			fi
		)
	done
}

_ping_server() {
	local servername="$1"
	[ -z "$servername" ] && return
	local disabled=$(uci -q get openmptcprouter."$servername".disabled)
	local device="$2"
	if [ -n "$device" ] && [ "$disabled" != "1" ]; then
		check_ping() {
			serverip="$1"
			if [ -n "$serverip" ]; then
				_ping "$serverip" "$device" "yes"
				statusp=$?
				if $(exit $statusp); then
					serverip_ping=true
					return 0
				fi
			fi
		}
		config_load openmptcprouter
		config_list_foreach "${servername}" ip check_ping
	fi
}

_ping_server_all() {
	count_server() {
		config_get disabled $1 disabled
		config_get serverip $1 ip
		if [ "$disabled" != "1" ] && [ -n "$serverip" ]; then
			servers=true
		fi
	}
	config_load openmptcprouter
	config_foreach count_server server
	if [ "$servers" = true ]; then
		for intf in $(multipath 2>/dev/null | awk '/default/ { print $1 }); do
			config_foreach _ping_server server $intf
		done
	fi
}

_httping_server() {
	local servername="$1"
	[ -z "$servername" ] && return
	local disabled=$(uci -q get openmptcprouter."$servername".disabled)
	local port=$(uci -q get openmptcprouter."$servername".port)
	local device="$2"
	if [ -n "$device" ] && [ "$disabled" != "1" ]; then
		check_ping() {
			serverip="$1"
			if [ -n "$serverip" ]; then
				_httping "${serverip}:${port}" "$device" "yes" true
				statusp=$?
				if $(exit $statusp); then
					serverip_ping=true
					return 0
				fi
			fi
		}
		config_load openmptcprouter
		config_list_foreach "${servername}" ip check_ping
	fi
}

_httping_server_all() {
	count_server() {
		config_get disabled $1 disabled
		config_get serverip $1 ip
		if [ "$disabled" != "1" ] && [ -n "$serverip" ]; then
			servers=true
		fi
	}
	config_load openmptcprouter
	config_foreach count_server server
	if [ "$servers" = true ]; then
		for intf in $(multipath 2>/dev/null | awk '/default/ { print $1 }); do
			config_foreach _httping_server server $intf
		done
	fi
}


_ping() {
	local host="$1"
	[ -z "$host" ] && return
	local device="$2"
	local localip="$3"
	if [ -n "$OMR_TRACKER_INTERFACE" ] && { [ "$OMR_TRACKER_NO_BIND" = "1" ] || [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "3g" ] || [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "qmi" ] || [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "ncm" ]; }; then
		ret=$(ping -I "${device}" \
			-w "$OMR_TRACKER_TIMEOUT" \
			-c "$OMR_TRACKER_COUNT" \
			-s "$OMR_TRACKER_SIZE" \
			-t "$OMR_TRACKER_MAX_TTL" \
			-Q 184 \
			"${host}" 2>&1
		)
		loss=$(echo "$ret" | awk '/packet loss/ && !/errors/ {gsub("%","");print $6}' | tr -d '\n')
		
		if [ -n "$loss" ] && [ "$loss" != "100" ]; then
			if [ "$localip" = "yes" ]; then
				latency=$(echo "$ret" | awk -F/ '/rtt/ {print int($5)}' | tr -d '\n')
				[ -n "$latency" ] && {
					OMR_TRACKER_LATENCY="$latency"
					#_update_rto "$OMR_TRACKER_LATENCY"
				}
				OMR_TRACKER_LOSS="$loss"
			fi
			return 0
		fi
	else
		ret=$(ping -B -I "${device}" \
			-w "$OMR_TRACKER_TIMEOUT" \
			-c "$OMR_TRACKER_COUNT" \
			-s "$OMR_TRACKER_SIZE" \
			-t "$OMR_TRACKER_MAX_TTL" \
			-Q 184 \
			"${host}" 2>&1
		)
		bindcheck=$(echo "$ret" | grep "Address not available")
		[ -n "$bindcheck" ] && OMR_TRACKER_NO_BIND=1
		loss=$(echo "$ret" | awk '/packet loss/ && !/errors/  {gsub("%","");print $6}' | tr -d '\n')
		if [ -n "$loss" ] && [ "$loss" != "100" ]; then
			if [ "$localip" = "yes" ]; then
				#latency=$(echo "$ret" | grep rtt | cut -d "/" -s -f5 | cut -d "." -f1 | tr -d '\n')
				latency=$(echo "$ret" | awk -F/ '/rtt/ {print int($5)}' | tr -d '\n')
				[ -n "$latency" ] && {
					OMR_TRACKER_LATENCY="$latency"
					#_update_rto "$OMR_TRACKER_LATENCY"
				}
				OMR_TRACKER_LOSS="$loss"
			fi
			return 0
		fi
	fi
	return 1
}
#'
_httping() {
	local host=$1
	local deviceip=$2
	local localip=$3
	local https=$4
	if [ -z "$https" ] || [ "$https" = false ]; then
		ret=$(httping "${host}" \
			-y "${deviceip}" \
			-t "$OMR_TRACKER_TIMEOUT" \
			-c "$OMR_TRACKER_COUNT" 2>&1
		)
		bindcheck=$(echo "$ret" | grep "Address not available")
		[ -n "$bindcheck" ] && OMR_TRACKER_NO_BIND=1
		loss=$(echo "$ret" | awk '/failed/ {gsub("%",""); print int($5)}' | tr -d '\n')
		if [ -n "$loss" ] && [ "$loss" != "100" ]; then
			if [ "$localip" = "yes" ]; then
				latency=$(echo "$ret" | cut -d "/" -s -f5 | cut -d "." -f1 | tr -d '\n')
				[ -n "$latency" ] && {
					OMR_TRACKER_LATENCY="$latency"
					#_update_rto "$OMR_TRACKER_LATENCY"
				}
				OMR_TRACKER_LOSS="$loss"
			fi
			return 0
		fi
	else
		ret=$(httping -l "${host}" \
			-y "${deviceip}" \
			-t "$OMR_TRACKER_TIMEOUT" \
			-c "$OMR_TRACKER_COUNT" 2>&1
		)
		bindcheck=$(echo "$ret" | grep "Address not available")
		[ -n "$bindcheck" ] && OMR_TRACKER_NO_BIND=1
		loss=$(echo "$ret" | awk '/failed/ {gsub("%",""); print int($5)}' | tr -d '\n')
		if [ -n "$loss" ] && [ "$loss" != "100" ]; then
			if [ "$localip" = "yes" ]; then
				latency=$(echo "$ret" | cut -d "/" -s -f5 | cut -d "." -f1 | tr -d '\n')
				[ -n "$latency" ] && {
					OMR_TRACKER_LATENCY="$latency"
					#_update_rto "$OMR_TRACKER_LATENCY"
				}
				OMR_TRACKER_LOSS="$loss"
			fi
			return 0
		fi
	fi
	return 1
}

_dns() {
	local host=$1
	local deviceip=$2
	ret=$(dig @"${host}" \
		-b "${deviceip}" \
		    +time="$OMR_TRACKER_TIMEOUT" \
		    +tries="$OMR_TRACKER_COUNT" \
		    one.one.one.one
	) && echo "$ret" | grep -sq "1.1.1.1" && {
		OMR_TRACKER_LATENCY=$(echo "$ret" | awk '/Query time/{print $4}')
		#_update_rto "$OMR_TRACKER_LATENCY"
		return 0
	}
	return 1
}

_none() {
	return 0
}

_restart

OMR_TRACKER_INTERFACE_PROTO="$(uci -q get network.${OMR_TRACKER_INTERFACE}.proto)"
OMR_TRACKER_PREV_STATUS=""
[ "$OMR_TRACKER_INTERFACE_PROTO" = "modemmanager" ] && sleep $(uci -q get network.${OMR_TRACKER_INTERFACE}.delay || echo '120')

# main loop
while true; do
	# setup tracker variables
	OMR_TRACKER_DEVICE_IP=
	OMR_TRACKER_DEVICE_IP6=
	OMR_TRACKER_STATUS="ERROR"
	OMR_TRACKER_STATUS_MSG=""
	OMR_TRACKER_LATENCY=
	OMR_TRACKER_LOSS=
	#OMR_TRACKER_TIMEOUT=$((rto / 1000 + (rto % 1000 ? 1 : 0)))
	OMR_TRACKER_LIST_HOSTS=""
	OMR_TRACKER_DEVICE_GATEWAY=
	OMR_TRACKER_DEVICE_GATEWAY6=
	serverip_ping=false
	[ -z "$OMR_TRACKER_DEVICE" ] || [ -d "/sys/class/net/$OMR_TRACKER_DEVICE" ] && {
			[ -z "$OMR_TRACKER_DEVICE" ] && OMR_TRACKER_DEVICE=$(ifstatus "$OMR_TRACKER_INTERFACE" | jsonfilter -q -e '@["l3_device"]')
			[ -z "$OMR_TRACKER_DEVICE" ] && OMR_TRACKER_DEVICE=$(ifstatus "${OMR_TRACKER_INTERFACE}_4" | jsonfilter -q -e '@["l3_device"]')
			#[ -z "$OMR_TRACKER_DEVICE" ] && config_get OMR_TRACKER_DEVICE "$OMR_TRACKER_INTERFACE" device
			[ -n "$(echo $OMR_TRACKER_DEVICE | grep '@')" ] && OMR_TRACKER_DEVICE=$(ifstatus "$OMR_TRACKER_INTERFACE" | jsonfilter -q -e '@["device"]')
			[ -z "$OMR_TRACKER_DEVICE" ] && network_get_physdev OMR_TRACKER_DEVICE "$OMR_TRACKER_INTERFACE"
			[ -z "$OMR_TRACKER_DEVICE" ] && network_get_device OMR_TRACKER_DEVICE "$OMR_TRACKER_INTERFACE"
	}

	if [ -n "$OMR_TRACKER_DEVICE" ] && [ -d "/sys/class/net/$OMR_TRACKER_DEVICE" ]; then
		OMR_TRACKER_PREV_DEVICE="$OMR_TRACKER_DEVICE"
		OMR_TRACKER_DEVICE_STATE=$(ip -j link show dev "$OMR_TRACKER_DEVICE" | jsonfilter -q -e '@[*].operstate' | tr -d '\n')
		if ([ "$(ifstatus $OMR_TRACKER_INTERFACE | jsonfilter -q -e '@.up')" == "true" ] && [ "$OMR_TRACKER_DEVICE_STATE" != "DOWN" ]) || [ "$OMR_TRACKER_INTERFACE" = "omrvpn" ]; then
			# retrieve iface ip and gateway
			if { [ "$OMR_TRACKER_FAMILY" = "ipv4" ] || [ "$OMR_TRACKER_FAMILY" = "ipv4ipv6" ]; } && [ "$OMR_TRACKER_INTERFACE_PROTO" != "dhcpv6" ]; then
				OMR_TRACKER_DEVICE_IP=$(ip -4 -br addr ls dev "$OMR_TRACKER_DEVICE" | awk -F'[ /]+' '{print $3}')
				if [ -z "$OMR_TRACKER_DEVICE_IP" ]; then
					OMR_TRACKER_DEVICE_IP=$(ip -4 addr show dev "$OMR_TRACKER_DEVICE" | grep -m 1 inet | awk '{print $2}' | cut -d'/' -s -f1)
				fi
				#OMR_TRACKER_DEVICE_IP=$(ubus call network.interface.$OMR_TRACKER_INTERFACE status | jsonfilter -q -e '@["ipv4-address"][0].address' | tr -d "\n")
				#if [ -z "$OMR_TRACKER_DEVICE_GATEWAY" ]; then
				#	OMR_TRACKER_DEVICE_GATEWAY=$(ip -4 r list dev "$OMR_TRACKER_DEVICE" | grep -v default | awk '/proto static/ {print $1}' | tr -d "\n")
				#fi
				if [ "$OMR_TRACKER_DEVICE" = "bonding-omrvpn" ]; then
					OMR_TRACKER_DEVICE_GATEWAY="10.255.248.1"
				fi
				if [ -z "$OMR_TRACKER_DEVICE_GATEWAY" ]; then
					OMR_TRACKER_DEVICE_GATEWAY=$(uci -q get "network.$OMR_TRACKER_INTERFACE.gateway")
				fi
				if [ -z "$OMR_TRACKER_DEVICE_GATEWAY" ] || [ "$OMR_TRACKER_DEVICE_GATEWAY" = "0.0.0.0" ]; then
					OMR_TRACKER_DEVICE_GATEWAY=$(ubus call network.interface.$OMR_TRACKER_INTERFACE status | jsonfilter -q -l 1 -e '@.inactive.route[@.target="0.0.0.0"].nexthop' | tr -d "\n")
				fi
				if [ -z "$OMR_TRACKER_DEVICE_GATEWAY" ] || [ "$OMR_TRACKER_DEVICE_GATEWAY" = "0.0.0.0" ]; then
					OMR_TRACKER_DEVICE_GATEWAY=$(ubus call network.interface.$OMR_TRACKER_INTERFACE status | jsonfilter -q -l 1 -e '@.route[@.target="0.0.0.0"].nexthop' | tr -d "\n")
				fi
				if [ -z "$OMR_TRACKER_DEVICE_GATEWAY" ] || [ "$OMR_TRACKER_DEVICE_GATEWAY" = "0.0.0.0" ]; then
					OMR_TRACKER_DEVICE_GATEWAY=$(ubus call network.interface.${OMR_TRACKER_INTERFACE}_4 status 2>/dev/null | jsonfilter -q -l 1 -e '@.inactive.route[@.target="0.0.0.0"].nexthop' | tr -d "\n")
				fi
				if [ -z "$OMR_TRACKER_DEVICE_GATEWAY" ] || [ "$OMR_TRACKER_DEVICE_GATEWAY" = "0.0.0.0" ]; then
					if [ "$OMR_TRACKER_INTERFACE" = "omrvpn" ] && [ "$(uci -q get glorytun.vpn.enable)" = "1" ]; then
						OMR_TRACKER_DEVICE_GATEWAY=$(uci -q get glorytun.vpn.remoteip)
					elif [ "$OMR_TRACKER_INTERFACE" = "omrvpn" ] && [ "$(uci -q get glorytun-udp.vpn.enable)" = "1" ]; then
						OMR_TRACKER_DEVICE_GATEWAY=$(uci -q get glorytun-udp.vpn.remoteip)
					else
						OMR_TRACKER_DEVICE_GATEWAY=""
					fi
				fi
				if [ -z "$OMR_TRACKER_DEVICE_GATEWAY" ]; then
					OMR_TRACKER_DEVICE_ROUTE=$(ip -4 r list dev "$OMR_TRACKER_DEVICE" | grep via | grep -v default | grep -v nexthop | grep -v metric | grep -v / | awk '{print $1; exit}' | tr -d "\n")
				fi
				if [ -z "$OMR_TRACKER_DEVICE_GATEWAY" ]; then
					OMR_TRACKER_DEVICE_GATEWAY=$(ip -4 r list dev "$OMR_TRACKER_DEVICE" | grep kernel | grep -v '.0/' | awk '/proto kernel/ {print $1;exit}' | tr -d "\n")
				fi
				if [ -z "$OMR_TRACKER_DEVICE_GATEWAY" ]; then
					OMR_TRACKER_DEVICE_GATEWAY=$(ip -4 r list dev "$OMR_TRACKER_DEVICE" | grep -m 1 default | awk '/via/ {print $3;exit}' | tr -d "\n")
				fi
				if [ -z "$OMR_TRACKER_DEVICE_GATEWAY" ]; then
					OMR_TRACKER_DEVICE_GATEWAY=$(ip -4 r list dev "$OMR_TRACKER_DEVICE" | awk '/via/ {print $3;exit}' | tr -d "\n")
				fi
				if [ -z "$OMR_TRACKER_DEVICE_GATEWAY" ] && [ "$OMR_TRACKER_INTERFACE" = "omrvpn" ] && [ "$(uci -q get openvpn.omr.enabled)" = "1" ]; then
					OMR_TRACKER_DEVICE_GATEWAY="10.255.252.1"
				fi

			fi
			if { [ "$OMR_TRACKER_IPV6" = "1" ] || [ "$OMR_TRACKER_IPV6" = "auto" ]; } && { [ "$OMR_TRACKER_FAMILY" = "ipv6" ] || [ "$OMR_TRACKER_FAMILY" = "ipv4ipv6" ]; }; then
				#OMR_TRACKER_DEVICE_IP6=$(ip -6 -br addr ls dev "$OMR_TRACKER_DEVICE" | awk -F'[ /]+' '{print $3}')
				#if [ -z "$OMR_TRACKER_DEVICE_IP6" ]; then
					OMR_TRACKER_DEVICE_IP6=$(ip -6 addr show dev "$OMR_TRACKER_DEVICE" scope global | sort -r | grep -m 1 inet6 | awk '{print $2}' | cut -d'/' -s -f1)
				#fi
				if [ -z "$OMR_TRACKER_DEVICE_GATEWAY6" ]; then
					OMR_TRACKER_DEVICE_GATEWAY6=$(uci -q get "network.$OMR_TRACKER_INTERFACE.ip6gw")
				fi
				if [ -z "$OMR_TRACKER_DEVICE_GATEWAY6" ] || [ "$OMR_TRACKER_DEVICE_GATEWAY6" = "::" ]; then
					OMR_TRACKER_DEVICE_GATEWAY6=$(ubus call network.interface.${OMR_TRACKER_INTERFACE} status 2>/dev/null | jsonfilter -q -l 1 -e "@.inactive.route[@.source=\"${OMR_TRACKER_DEVICE_IP6}\"].nexthop" | tr -d "\n")
				fi
				if [ -z "$OMR_TRACKER_DEVICE_GATEWAY6" ] || [ "$OMR_TRACKER_DEVICE_GATEWAY6" = "::" ]; then
					OMR_TRACKER_DEVICE_GATEWAY6=$(ubus call network.interface.${OMR_TRACKER_INTERFACE} status 2>/dev/null | jsonfilter -q -l 1 -e "@.inactive.route[@.source=\"${OMR_TRACKER_DEVICE_IP6}/64\"].nexthop" | tr -d "\n")
				fi
				if [ -z "$OMR_TRACKER_DEVICE_GATEWAY6" ] || [ "$OMR_TRACKER_DEVICE_GATEWAY6" = "::" ]; then
					OMR_TRACKER_DEVICE_GATEWAY6=$(ubus call network.interface.${OMR_TRACKER_INTERFACE} status 2>/dev/null | jsonfilter -q -l 1 -e "@.inactive.route[@.source=\"${OMR_TRACKER_DEVICE_IP6}/56\"].nexthop" | tr -d "\n")
				fi
				if [ -z "$OMR_TRACKER_DEVICE_GATEWAY6" ] || [ "$OMR_TRACKER_DEVICE_GATEWAY6" = "::" ]; then
					OMR_TRACKER_DEVICE_GATEWAY6=$(ubus call network.interface.$OMR_TRACKER_INTERFACE status | jsonfilter -q -l 1 -e '@.route[@.target="::"].nexthop' | tr -d "\n")
				fi
				if [ -z "$OMR_TRACKER_DEVICE_GATEWAY6" ] || [ "$OMR_TRACKER_DEVICE_GATEWAY6" = "::" ]; then
					OMR_TRACKER_DEVICE_GATEWAY6=$(ubus call network.interface.$OMR_TRACKER_INTERFACE status | jsonfilter -q -l 1 -e '@.route[@.nexthop="::"].target' | tr -d "\n")
				fi
			fi

			# execute specific tracker
			if { [ "$OMR_TRACKER_FAMILY" = "ipv4" ] || [ "$OMR_TRACKER_FAMILY" = "ipv4ipv6" ]; } && [ -n "$OMR_TRACKER_DEVICE_IP" ] && [ -n "$OMR_TRACKER_DEVICE_GATEWAY" ]; then
				# setup loop variable
				if [ "$OMR_TRACKER_PREV_STATUS" = "ERROR" ]; then
					tries="$OMR_TRACKER_TRIES_UP"
				else
					tries="$OMR_TRACKER_TRIES"
				fi
				# loop until tries attempts have been reached
				while [ "$tries" -gt 0 ]; do
					if [ "$OMR_TRACKER_TYPE" = "glorytun-udp" ]; then
						glorytun_state="$(glorytun-udp path addr $OMR_TRACKER_DEVICE_IP | awk '/path/ { print $4 }' | tr -d '\n')"
						if [ "$glorytun_state" = "running" ]; then
							OMR_TRACKER_STATUS_MSG=""
							OMR_TRACKER_STATUS="OK"
						else
							OMR_TRACKER_STATUS_MSG="Glorytun-UDP path $OMR_TRACKER_DEVICE_IP ($OMR_TRACKER_INTERFACE) is $glorytun_state"
							OMR_TRACKER_STATUS="ERROR"
						fi
						break
					fi
					if [ -n "$OMR_TRACKER_DEVICE_ROUTE" ]; then
						_ping "$OMR_TRACKER_DEVICE_ROUTE" "$OMR_TRACKER_DEVICE" "no"
						status=$?
					else
						_ping "$OMR_TRACKER_DEVICE_GATEWAY" "$OMR_TRACKER_DEVICE" "no"
						status=$?
					fi
					if $(exit $status) && [ "$OMR_TRACKER_TYPE" = "none" ]; then
						OMR_TRACKER_STATUS_MSG=""
						OMR_TRACKER_STATUS="OK"
						break
					elif [ "$OMR_TRACKER_TYPE" != "none" ]; then
						if ! $(exit $status); then
							OMR_TRACKER_STATUS_MSG="IPv4 gateway down"
						fi
						serverip_ping=false
						if [ "$OMR_TRACKER_TYPE" = "ping" ]; then
							config_load openmptcprouter
							config_foreach _ping_server server $OMR_TRACKER_DEVICE
						fi
						if [ "$OMR_TRACKER_TYPE" = "httping" ]; then
							config_load openmptcprouter
							config_foreach _httping_server server $OMR_TRACKER_DEVICE
						fi
						if [ "$serverip_ping" = false ] && [ -n "$OMR_TRACKER_HOST" ]; then
							OMR_TRACKER_HOST=$(resolveip -4 -t 5 $OMR_TRACKER_HOST | head -n 1 | tr -d "\n")
							if [ -n "$OMR_TRACKER_HOST" ]; then
								if [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "3g" ] || [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "qmi" ] || [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "ncm" ]; then
									# Check if route is not used
									while ! ip route add $OMR_TRACKER_HOST via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE src $OMR_TRACKER_DEVICE_IP > /dev/null 2>&1
									do
										logger -t "omr-tracker" "Can't create route to $OMR_TRACKER_HOST via $OMR_TRACKER_DEVICE_GATEWAY dev $OMR_TRACKER_DEVICE src $OMR_TRACKER_DEVICE_IP. waiting..."
										sleep 2
										ip route del "$OMR_TRACKER_HOST" via "$OMR_TRACKER_DEVICE_GATEWAY" dev "$OMR_TRACKER_DEVICE" src "$OMR_TRACKER_DEVICE_IP" > /dev/null 2>&1
										_restart
									done
								fi
								if [ "$OMR_TRACKER_TYPE" = "ping" ]; then
									_ping "$OMR_TRACKER_HOST" "$OMR_TRACKER_DEVICE" "yes"
									statusb=$?
								elif [ "$OMR_TRACKER_TYPE" = "httping" ]; then
									_httping "$OMR_TRACKER_HOST" "$OMR_TRACKER_DEVICE_IP" "yes"
									statusb=$?
								elif [ "$OMR_TRACKER_TYPE" = "dns" ]; then
									_dns "$OMR_TRACKER_HOST" "$OMR_TRACKER_DEVICE_IP" "yes"
									statusb=$?
								fi
								[ -n "$(ip route show ${OMR_TRACKER_HOST} via ${OMR_TRACKER_DEVICE_GATEWAY} dev ${OMR_TRACKER_DEVICE} src ${OMR_TRACKER_DEVICE_IP})" ] && ip route del "$OMR_TRACKER_HOST" via "$OMR_TRACKER_DEVICE_GATEWAY" dev "$OMR_TRACKER_DEVICE" src "$OMR_TRACKER_DEVICE_IP" > /dev/null 2>&1
								if $(exit $statusb); then
									#OMR_TRACKER_STATUS_MSG=""
									OMR_TRACKER_STATUS="OK"
								else
									if [ "$OMR_TRACKER_LIST_HOSTS" = "" ]; then
										OMR_TRACKER_LIST_HOSTS="$OMR_TRACKER_HOST"
									else
										OMR_TRACKER_LIST_HOSTS="$OMR_TRACKER_LIST_HOSTS,$OMR_TRACKER_HOST"
									fi
									OMR_TRACKER_STATUS_MSG="check error"
								fi
							fi
						else
							#OMR_TRACKER_STATUS_MSG=""
							OMR_TRACKER_STATUS="OK"
						fi
						if [ "$serverip_ping" != false ] && [ "$OMR_TRACKER_STATUS" = "OK" ] && [ "$OMR_TRACKER_TYPE" != "httping" ] && [ "$OMR_TRACKER_SERVER_HTTP_TEST" = "1" ]; then
							serverip_ping=false
							config_load openmptcprouter
							config_foreach _httping_server server $OMR_TRACKER_DEVICE_IP
							if [ "$serverip_ping" = false ]; then
								#OMR_TRACKER_STATUS="ERROR"
								OMR_TRACKER_STATUS_MSG="$OMR_TRACKER_STATUS_MSG No access to server API"
							else
								OMR_TRACKER_STATUS_MSG=""
								OMR_TRACKER_STATUS="OK"
								break
							fi
						elif [ "$serverip_ping" = false ] && [ "$OMR_TRACKER_STATUS" = "OK" ] && [ "$OMR_TRACKER_SERVER_TEST" = "1" ]; then
							if [ "$OMR_TRACKER_TYPE" = "ping" ]; then
								_ping_server_all
							fi
							if [ "$OMR_TRACKER_TYPE" = "httping" ]; then
								_httping_server_all
							fi
							if [ "$server_ping" != false ] && [ "$servers" = true ]; then
								OMR_TRACKER_STATUS_MSG="$OMR_TRACKER_STATUS_MSG No answer from server"
								OMR_TRACKER_STATUS="ERROR"
								break
							fi
						fi
						[ "$OMR_TRACKER_STATUS" = "OK" ] && break
					elif ! $(exit $status); then
						OMR_TRACKER_STATUS_MSG="IPv4 gateway down"
					fi
					tries=$((tries - 1))
					#_restart
					OMR_TRACKER_HOST="${OMR_TRACKER_HOSTS%% *}"
					[ "$OMR_TRACKER_HOST" = "$OMR_TRACKER_HOSTS" ] || {
						OMR_TRACKER_HOSTS="${OMR_TRACKER_HOSTS#* } $OMR_TRACKER_HOST"
					}
					#OMR_TRACKER_TIMEOUT=$((OMR_TRACKER_TIMEOUT * 2))
					sleep "${OMR_TRACKER_INTERVAL_TRIES:-1}"
				done
			fi
			#if [ "$(uci -q get openmptcprouter.settings.disable_ipv6)" = "0" ] && [ -n "$OMR_TRACKER_DEVICE_IP6" ] && [ -n "$OMR_TRACKER_DEVICE_GATEWAY6" ]; then
			if [ -n "$OMR_TRACKER_DEVICE_IP6" ] && [ -n "$OMR_TRACKER_DEVICE_GATEWAY6" ]; then
				# setup loop variable
				if [ "$OMR_TRACKER_PREV_STATUS" = "ERROR" ]; then
					tries="$OMR_TRACKER_TRIES"
				else
					tries="$OMR_TRACKER_TRIES_UP"
				fi
				# loop until tries attempts have been reached
				while [ "$tries" -gt 0 ]; do
					#if [ -n "$OMR_TRACKER_DEVICE_ROUTE" ]; then
					#	_ping "$OMR_TRACKER_DEVICE_ROUTE" "$OMR_TRACKER_DEVICE" "no"
					#	status=$?
					#else
						_ping "$OMR_TRACKER_DEVICE_GATEWAY6" "$OMR_TRACKER_DEVICE" "no"
						status=$?
					#fi
					if $(exit $status) && [ "$OMR_TRACKER_TYPE" = "none" ]; then
						OMR_TRACKER_STATUS_MSG=""
						OMR_TRACKER_STATUS="OK"
						break
					elif [ "$OMR_TRACKER_TYPE" != "none" ]; then
						if ! $(exit $status); then
							OMR_TRACKER_STATUS_MSG="IPv6 gateway down"
						fi
						serverip_ping=false
						if [ "$OMR_TRACKER_TYPE" = "ping" ]; then
							config_load openmptcprouter
							config_foreach _ping_server server $OMR_TRACKER_DEVICE
						fi
						if [ "$OMR_TRACKER_TYPE" = "httping" ]; then
							config_load openmptcprouter
							config_foreach _httping_server server $OMR_TRACKER_DEVICE
						fi

						if [ "$serverip_ping" = false ] && [ -n "$OMR_TRACKER_HOST6" ]; then
							OMR_TRACKER_HOST6=$(resolveip -6 -t 5 $OMR_TRACKER_HOST6 | head -n 1 | tr -d "\n")
							if [ -n "$OMR_TRACKER_HOST6" ]; then
								if [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "3g" ] || [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "qmi" ] || [ "$(uci -q get network.$OMR_TRACKER_INTERFACE.proto)" = "ncm" ]; then
									# Check if route is not used
									while ! ip -6 route add $OMR_TRACKER_HOST6 via $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE src $OMR_TRACKER_DEVICE_IP6 > /dev/null 2>&1
									do
										logger -t "omr-tracker" "Can't create route to $OMR_TRACKER_HOST6 via $OMR_TRACKER_DEVICE_GATEWAY6 dev $OMR_TRACKER_DEVICE src $OMR_TRACKER_DEVICE_IP6. waiting..."
										sleep 2
										ip -6 route del "$OMR_TRACKER_HOST6" via "$OMR_TRACKER_DEVICE_GATEWAY6" dev "$OMR_TRACKER_DEVICE" src "$OMR_TRACKER_DEVICE_IP6" > /dev/null 2>&1
										_restart
									done
								fi
								if [ "$OMR_TRACKER_TYPE" = "ping" ]; then
									_ping "$OMR_TRACKER_HOST6" "$OMR_TRACKER_DEVICE" "yes"
									statusb=$?
								elif [ "$OMR_TRACKER_TYPE" = "httping" ]; then
									_httping "$OMR_TRACKER_HOST6" "$OMR_TRACKER_DEVICE_IP6" "yes"
									statusb=$?
								elif [ "$OMR_TRACKER_TYPE" = "dns" ]; then
									_dns "$OMR_TRACKER_HOST6" "$OMR_TRACKER_DEVICE_IP6" "yes"
									statusb=$?
								fi
								ip -6 route del "$OMR_TRACKER_HOST6" via "$OMR_TRACKER_DEVICE_GATEWAY6" dev "$OMR_TRACKER_DEVICE" src "$OMR_TRACKER_DEVICE_IP6" > /dev/null 2>&1
								if $(exit $statusb); then
									OMR_TRACKER_STATUS_MSG=""
									OMR_TRACKER_STATUS="OK"
								else
									if [ "$OMR_TRACKER_LIST_HOSTS6" = "" ]; then
										OMR_TRACKER_LIST_HOSTS6="$OMR_TRACKER_HOST6"
									else
										OMR_TRACKER_LIST_HOSTS6="$OMR_TRACKER_LIST_HOSTS6,$OMR_TRACKER_HOST6"
									fi
									OMR_TRACKER_STATUS_MSG="check error"
								fi
							fi
						else
							OMR_TRACKER_STATUS_MSG=""
							OMR_TRACKER_STATUS="OK"
						fi
						if [ "$serverip_ping" != false ] && [ "$OMR_TRACKER_STATUS" = "OK" ] && [ "$OMR_TRACKER_TYPE" != "httping" ] && [ "$OMR_TRACKER_SERVER_HTTP_TEST" = "1" ]; then
							serverip_ping=false
							config_load openmptcprouter
							config_foreach _httping_server server $OMR_TRACKER_DEVICE_IP6
							if [ "$serverip_ping" = false ]; then
								OMR_TRACKER_STATUS_MSG="No access to server API"
								#OMR_TRACKER_STATUS="ERROR"
							else
								OMR_TRACKER_STATUS_MSG=""
								OMR_TRACKER_STATUS="OK"
								break
							fi
						elif [ "$serverip_ping" = false ] && [ "$OMR_TRACKER_STATUS" = "OK" ] && [ "$OMR_TRACKER_SERVER_TEST" = "1" ]; then
							if [ "$OMR_TRACKER_TYPE" = "ping" ]; then
								_ping_server_all
							fi
							if [ "$OMR_TRACKER_TYPE" = "httping" ]; then
								_httping_server_all
							fi
							if [ "$server_ping" != false ] && [ "$servers" = true ]; then
								OMR_TRACKER_STATUS_MSG="$OMR_TRACKER_STATUS_MSG No answer from server"
								OMR_TRACKER_STATUS="ERROR"
								#break
							fi
						fi
						[ "$OMR_TRACKER_STATUS" = "OK" ] && break
					elif ! $(exit $status); then
						OMR_TRACKER_STATUS_MSG="IPv6 gateway down"
					fi
					tries=$((tries - 1))
					#_restart
					OMR_TRACKER_HOST6="${OMR_TRACKER_HOSTS6%% *}"
					[ "$OMR_TRACKER_HOST6" = "$OMR_TRACKER_HOSTS6" ] || {
						OMR_TRACKER_HOSTS6="${OMR_TRACKER_HOSTS6#* } $OMR_TRACKER_HOST6"
					}
					#OMR_TRACKER_TIMEOUT=$((OMR_TRACKER_TIMEOUT * 2))
					sleep "${OMR_TRACKER_INTERVAL_TRIES:-1}"
				done
			fi
			if [ "$OMR_TRACKER_STATUS" = "ERROR" ] && { [ -z "$OMR_TRACKER_DEVICE_IP" ] || [ -z "$OMR_TRACKER_DEVICE_GATEWAY" ] || [ -z "$OMR_TRACKER_DEVICE_IP6" ] || [ -z "$OMR_TRACKER_DEVICE_GATEWAY6" ]; }; then
				[ -z "$OMR_TRACKER_STATUS_MSG" ] && OMR_TRACKER_STATUS_MSG="$OMR_TRACKER_INTERFACE may have ip issues"
				[ -z "$OMR_TRACKER_DEVICE_IP" ] && OMR_TRACKER_STATUS_MSG="$OMR_TRACKER_STATUS_MSG, interface have no IPv4"
				[ -z "$OMR_TRACKER_DEVICE_GATEWAY" ] && OMR_TRACKER_STATUS_MSG="$OMR_TRACKER_STATUS_MSG, interface have no IPv4 gateway"
				[ "$OMR_TRACKER_IPV6" != "0" ] && [ -z "$OMR_TRACKER_DEVICE_IP6" ] && OMR_TRACKER_STATUS_MSG="$OMR_TRACKER_STATUS_MSG, interface have no IPv6"
				[ "$OMR_TRACKER_IPV6" != "0" ] && [ -z "$OMR_TRACKER_DEVICE_GATEWAY6" ] && OMR_TRACKER_STATUS_MSG="$OMR_TRACKER_STATUS_MSG, interface have no IPv6 gateway"
			elif [ "$OMR_TRACKER_STATUS" = "ERROR" ] && [ -z "$OMR_TRACKER_STATUS_MSG" ]; then
				OMR_TRACKER_STATUS_MSG="No IP & Gateway detected for $OMR_TRACKER_INTERFACE"
			fi
		else
			OMR_TRACKER_STATUS_MSG="link down"
		fi
	fi

	if [ "$OMR_TRACKER_LIST_HOSTS" != "" ]; then
		if [ "$OMR_TRACKER_STATUS_MSG" = "" ]; then
			OMR_TRACKER_STATUS_MSG="$OMR_TRACKER_TYPE from $OMR_TRACKER_DEVICE_IP error ($OMR_TRACKER_LIST_HOSTS)"
		else
			OMR_TRACKER_STATUS_MSG="$OMR_TRACKER_STATUS_MSG and $OMR_TRACKER_TYPE from $OMR_TRACKER_DEVICE_IP error ($OMR_TRACKER_LIST_HOSTS)"
		fi
	fi
	if [ "$OMR_TRACKER_LIST_HOSTS6" != "" ]; then
		if [ "$OMR_TRACKER_STATUS_MSG" = "" ]; then
			OMR_TRACKER_STATUS_MSG="$OMR_TRACKER_TYPE from $OMR_TRACKER_DEVICE_IP6 error ($OMR_TRACKER_LIST_HOSTS6)"
		else
			OMR_TRACKER_STATUS_MSG="$OMR_TRACKER_STATUS_MSG and $OMR_TRACKER_TYPE from $OMR_TRACKER_DEVICE_IP6 error ($OMR_TRACKER_LIST_HOSTS6)"
		fi
	fi
	if [ "$OMR_TRACKER_CHECK_QUALITY" = "1" ]; then
		if [ "$OMR_TRACKER_PREV_STATUS" = "OK" ] && [ "$OMR_TRACKER_STATUS" = "OK" ]; then
			if [ -n "$OMR_TRACKER_LOSS" ] && [ -n "$OMR_TRACKER_RECOVERY_LOSS" ] && [ "$OMR_TRACKER_LOSS" -ge "$OMR_TRACKER_FAILURE_LOSS" ]; then
				OMR_TRACKER_STATUS="ERROR"
				OMR_TRACKER_STATUS_MSG="Packet loss is $OMR_TRACKER_LOSS this is more than failure limit defined at $OMR_TRACKER_FAILURE_LOSS"
			elif [ -n "$OMR_TRACKER_LATENCY" ] && [ -n "$OMR_TRACKER_FAILURE_LATENCY" ] && [ "$OMR_TRACKER_LATENCY" -ge "$OMR_TRACKER_FAILURE_LATENCY" ]; then
				OMR_TRACKER_STATUS="ERROR"
				OMR_TRACKER_STATUS_MSG="Latency is $OMR_TRACKER_LATENCY this is more than failure limit defined at $OMR_TRACKER_FAILURE_LATENCY"
			fi
		elif [ "$OMR_TRACKER_PREV_STATUS" = "ERROR" ] && [ "$OMR_TRACKER_STATUS" = "OK" ]; then
			if [ -n "$OMR_TRACKER_LOSS" ] && [ -n "$OMR_TRACKER_RECOVERY_LOSS" ] && [ "$OMR_TRACKER_LOSS" -ge "$OMR_TRACKER_RECOVERY_LOSS" ]; then
				OMR_TRACKER_STATUS="ERROR"
				OMR_TRACKER_STATUS_MSG="Packet loss is $OMR_TRACKER_LOSS this is more than recovery limit defined at $OMR_TRACKER_RECOVERY_LOSS"
			elif [ -n "$OMR_TRACKER_LATENCY" ] && [ -n "$OMR_TRACKER_RECOVERY_LATENCY" ] && [ "$OMR_TRACKER_LATENCY" -ge "$OMR_TRACKER_RECOVERY_LATENCY" ]; then
				OMR_TRACKER_STATUS="ERROR"
				OMR_TRACKER_STATUS_MSG="Latency is $OMR_TRACKER_LATENCY this is more than recovery limit defined at $OMR_TRACKER_RECOVERY_LATENCY"
			fi
		fi
	fi

	#[ "$OMR_TRACKER_HOSTS" = "$initial_hosts" ] || [ "$OMR_TRACKER_STATUS" = "OK" ] && _post_tracking
	#[ "$OMR_TRACKER_STATUS" = "ERROR" ] && _restart
	#[ "$OMR_TRACKER_STATUS" != "$OMR_TRACKER_PREV_STATUS" ] && _post_tracking
	_post_tracking
	[ "$OMR_TRACKER_STATUS" = "ERROR" ] && sleep $wait_test
	OMR_TRACKER_PREV_STATUS="$OMR_TRACKER_STATUS"
	OMR_TRACKER_PREV_DEVICE_IP="$OMR_TRACKER_DEVICE_IP"
	OMR_TRACKER_PREV_DEVICE_IP6="$OMR_TRACKER_DEVICE_IP6"
	_restart

	if [ "$OMR_TRACKER_STATUS" = "ERROR" ]; then
		[ -n "$OMR_TRACKER_FAILURE_INTERVAL" ] && sleep "$OMR_TRACKER_FAILURE_INTERVAL"
	else
		sleep "${OMR_TRACKER_INTERVAL:-2}"
	fi
done
