#!/bin/sh

. /lib/functions.sh
. /lib/functions/network.sh
. /lib/mwan3/mwan3.sh
. /lib/mwan3/common.sh

mwan3_rtmon_route_handle()
{
	config_load mwan3
	local section action route_line family tbl device metric tos dst line
	local route_device tid
	route_line=${1##"Deleted "}
	route_family=$2

	if [ "$route_family" = "ipv4" ]; then
		IP="$IP4"
	elif [ "$route_family" = "ipv6" ] && [ $NO_IPV6 -eq 0 ]; then
		IP="$IP6"
	else
		return
	fi

	if [ "$route_line" == "$1" ]; then
		action="add"
	else
		action="del"
	fi

	# never add default route lines, since this is handled elsewhere
	[ -z "${route_line##default*}" ] && return
	[ -z "${route_line##::/0*}" ] && return
	route_line=${route_line%% linkdown*}
	route_line=${route_line%% unreachable*}
	mwan3_update_dev_to_table
	mwan3_route_line_dev "tid" "$route_line" "$route_family"
	handle_route() {
		tbl=$($IP route list table $tid)
		if [ $action = "add" ]; then
			echo "$tbl" | grep -q "^default\|^::/0" || return
		else
			[ -z "$tbl" ] && return
		fi
		# check that action needs to be performed. May not need to take action if:
		# Got a route update on ipv6 where route is already in the table
		# Got a delete event, but table was already flushed

		[ $action = "add" ] && [ -z "${tbl##*$route_line*}" ] && return
		[ $action = "del" ] && [ -n "${tbl##*$route_line*}" ] && return
		network_get_device device "$section"
		LOG debug "adjusting route $device: $IP route "$action" table $tid $route_line"
		$IP route "$action" table $tid $route_line ||
			LOG warn "failed: $IP route $action table $tid $route_line"
	}
	handle_route_cb(){
		let tid++
		config_get family "$section" family ipv4
		[ "$family" != "$route_family" ] && return
		handle_route
	}

	if [ $action = "add" ]; then
		## handle old routes from 'change' or 'replace'
		metric=${route_line##*metric }
		[ "$metric" = "$route_line" ] && unset metric || metric=${metric%% *}

		tos=${route_line##*tos }
		[ "$tos" = "$route_line" ] && unset tos || tos=${tos%% *}

		dst=${route_line%% *}
		grep_line="$dst ${tos:+tos $tos}.*table [0-9].*${metric:+metric $metric}"
		$IP route list table all | grep "$grep_line" | while read line; do
			tbl=${line##*table }
			tbl=${tbl%% *}
			[ $tbl -gt $MWAN3_INTERFACE_MAX ] && continue
			LOG debug "removing route on ip route change/replace: $line"
			$IP route del $line
		done
	fi

	if [ -n "$tid" ]; then
		handle_route
	else
		config_foreach handle_route_cb interface
	fi
}

main()
{
	local IP family

	config_load mwan3
	family=$1
	[ -z $family ] && family=ipv4
	if [ "$family" = ipv6 ]; then
		IP="$IP6"
	else
		IP="$IP4"
	fi
	mwan3_init

	$IP monitor route | while read line; do
		[ -z "${line##*table*}" ] && continue
		LOG debug "handling route update $family $line"
		mwan3_lock "service" "mwan3rtmon"
		mwan3_rtmon_route_handle "$line" "$family"
		mwan3_unlock "service" "mwan3rtmon"
	done
}
main "$@"
