#!/bin/sh
. /lib/functions.sh

IP="/usr/sbin/ip -4"
IPS="/usr/sbin/ipset"
IPT="/usr/sbin/iptables -t mangle -w"

help()
{
	cat <<EOF
Syntax: mwan3 [command]

Available commands:
	start           Load iptables rules, ip rules and ip routes
	stop            Unload iptables rules, ip rules and ip routes
	restart         Reload iptables rules, ip rules and ip routes
        ifup <iface>    Load rules and routes for specific interface
        ifdown <iface>  Unload rules and routes for specific interface
        interfaces      Show interfaces status
        policies        Show policies status
        rules           Show rules status
        status          Show all status

EOF
}

ifdown()
{
	if [ -z "$1" ]; then
		echo "Error: Expecting interface. Usage: mwan3 ifdown <interface>" && exit 0
	fi

	if [ -n "$2" ]; then
		echo "Error: Too many arguments. Usage: mwan3 ifdown <interface>" && exit 0
	fi

	if [ -e /var/run/mwan3track-$1.pid ] ; then
		kill $(cat /var/run/mwan3track-$1.pid)
		rm /var/run/mwan3track-$1.pid
	fi

	ACTION=ifdown INTERFACE=$1 /sbin/hotplug-call iface
}

ifup()
{
	local device enabled

	config_load mwan3

	if [ -z "$1" ]; then
		echo "Expecting interface. Usage: mwan3 ifup <interface>" && exit 0
	fi

	if [ -n "$2" ]; then
		echo "Too many arguments. Usage: mwan3 ifup <interface>" && exit 0
	fi

	config_get enabled "$1" enabled 0

	device=$(uci -p /var/state get network.$1.ifname) &> /dev/null

	if [ -n "$device" ] ; then
		[ "$enabled" -eq 1 ] && ACTION=ifup INTERFACE=$1 DEVICE=$device /sbin/hotplug-call iface
	fi
}

interfaces()
{
	local device enabled iface_id tracking

	config_load mwan3

	echo "Interface status:"

	check_iface_status()
	{
		let iface_id++
		device=$(uci -p /var/state get network.$1.ifname) &> /dev/null

		if [ -z "$device" ]; then
			echo " interface $1 is unknown"
			return 0
		fi

		config_get enabled "$1" enabled 0

		if [ -n "$(ps -w | grep mwan3track | grep -v grep | sed '/.*\/usr\/sbin\/mwan3track \([^ ]*\) .*$/!d;s//\1/' | awk '$1 == "'$1'"')" ]; then
			tracking="active"
		else
			tracking="down"
		fi

		if [ -n "$($IP rule | awk '$5 == "'$device'"')" -a -n "$($IPT -S mwan3_iface_$1 2> /dev/null)" -a -n "$($IP route list table $iface_id default dev $device 2> /dev/null)" ]; then
			if [ -n "$(uci -p /var/state get mwan3.$1.track_ip 2> /dev/null)" ]; then
				echo " interface $1 is online (tracking $tracking)"
			else
				echo " interface $1 is online"
			fi
		elif [ -n "$($IP rule | awk '$5 == "'$device'"')" -o -n "$($IPT -S mwan3_iface_$1 2> /dev/null)" -o -n "$($IP route list table $iface_id default dev $device 2> /dev/null)" ]; then
			echo " interface $1 error"
		else
			if [ "$enabled" -eq 1 ]; then
				if [ -n "$(uci -p /var/state get mwan3.$1.track_ip 2> /dev/null)" ]; then
					echo " interface $1 is offline (tracking $tracking)"
				else
					echo " interface $1 is offline"
				fi
			else
				echo " interface $1 is disabled"
			fi
		fi
	}
	config_foreach check_iface_status interface
	echo -e
}

policies()
{
	local percent policy share total_weight weight iface

	for policy in $($IPT -S | awk '{print $2}' | grep mwan3_policy_ | sort -u); do
		echo "Policy $policy:" | sed 's/mwan3_policy_//'

		[ -n "$total_weight" ] || total_weight=$($IPT -S $policy | cut -s -d'"' -f2 | head -1 | awk '{print $3}')

		if [ ! -z "${total_weight##*[!0-9]*}" ]; then
			for iface in $($IPT -S $policy | cut -s -d'"' -f2 | awk '{print $1}'); do
				weight=$($IPT -S $policy | cut -s -d'"' -f2 | awk '$1 == "'$iface'"' | awk '{print $2}')
				percent=$(($weight*100/$total_weight))
				echo " $iface ($percent%)"
			done
		else
			echo " $($IPT -S $policy | sed '/.*--comment \([^ ]*\) .*$/!d;s//\1/;q')"
		fi

		echo -e

		unset iface
		unset total_weight
	done
}
rules()
{
	local address

	if [ -n "$($IPT -S mwan3_connected 2> /dev/null)" ]; then
		echo "Known networks:"
		for address in $($IPS list mwan3_connected | egrep '[0-9]{1,3}(\.[0-9]{1,3}){3}'); do
			echo " $address"
		done
		echo -e
	fi

	if [ -n "$($IPT -S mwan3_rules 2> /dev/null)" ]; then
		echo "Active rules:"
		$IPT -L mwan3_rules -n -v 2> /dev/null | tail -n+3 | sed 's/mark.*//' | sed 's/mwan3_policy_/- /' | sed 's/mwan3_rule_/S /'
		echo -e
	fi
}

status()
{
	interfaces
	policies
	rules
}

start()
{
	config_load mwan3
	config_foreach ifup interface
}

stop()
{
	local ipset route rule table

	killall mwan3track &> /dev/null
	rm /var/run/mwan3track-* &> /dev/null

	for route in $($IP route list table all | sed 's/.*table \([^ ]*\) .*/\1/' |  awk '{print $1}' | awk '{for(i=1;i<=NF;i++) if($i+0>0) if($i+0<255) {print;break}}'); do
		$IP route flush table $route &> /dev/null
	done

	for rule in $($IP rule list | egrep '^[1-2][0-9]{3}\:' | cut -d ':' -f 1); do
		$IP rule del pref $rule &> /dev/null
	done

	$IPT -D PREROUTING -j mwan3_hook &> /dev/null
	$IPT -D OUTPUT -j mwan3_hook &> /dev/null

	for table in $($IPT -S | awk '{print $2}' | grep mwan3 | sort -u); do
		$IPT -F $table &> /dev/null
	done

	for table in $($IPT -S | awk '{print $2}' | grep mwan3 | sort -u); do
		$IPT -X $table &> /dev/null
	done

	for ipset in $(ipset -n list | grep mwan3); do
		$IPS destroy $ipset
	done
}

restart() {
	stop
	start
}

case "$1" in
	ifup|ifdown|interfaces|policies|rules|status|start|stop|restart)
		$*
	;;
	*)
		help
	;;
esac

exit 0
