#!/bin/sh
# Copyright (C) 2018-2019 Ycarus (Yannick Chabanois) <ycarus@zugaina.org>

NET_CLASS_DIR=${NET_CLASS_DIR:-/sys/class/net}

while true; do
	iface=""
	addr=""
	peer=""
	if [ "$(uci -q get glorytun.vpn.enable)" = "1" ]; then
		iface=$(uci -q get glorytun.vpn.dev)
		addr=$(uci -q get glorytun.vpn.localip)
		peer=$(uci -q get glorytun.vpn.remoteip)
	elif [ "$(uci -q get glorytun-udp.vpn.enable)" = "1" ]; then
		iface=$(uci -q get glorytun-udp.vpn.dev)
		addr=$(uci -q get glorytun-udp.vpn.localip)
		peer=$(uci -q get glorytun-udp.vpn.remoteip)
	elif [ "$(uci -q get dsvpn.vpn.enable)" = "1" ]; then
		iface=$(uci -q get dsvpn.vpn.dev)
		addr=$(uci -q get dsvpn.vpn.localip)
		peer=$(uci -q get dsvpn.vpn.remoteip)
	elif [ "$(uci -q get mqvpn.settings.enable)" = "1" ]; then
		iface=$(uci -q get mqvpn.interface.tun_name)
	elif [ "$(uci -q get mlvpn.general.enable)" = "1" ]; then
		iface=$(uci -q get mlvpn.general.interface_name)
	elif [ "$(uci -q get openvpn.omr.enabled)" = "1" ]; then
		iface=$(uci -q get openvpn.omr.dev)
	elif [ "$(uci -q get softethervpn.openmptcprouter.enable)" = "1" ]; then
		iface="vpn_softether"
	fi
	[ -z "$addr" ] && addr=$(ubus call network.interface.omrvpn status | jsonfilter -q -e '@["ipv4-address"][0].address' | tr -d "\n")
	if [ -n "$iface" ] && [ -d "${NET_CLASS_DIR}/$iface" ]; then
		[ -z "$addr" ] && addr=$(ip -4 addr show dev "$iface" | grep inet | awk '{print $2}' | cut -d/ -f1 | tr -d "\n")
		[ -z "$peer" ] && peer=$(ubus call network.interface.omrvpn status | jsonfilter -q -l 1 -e '@.route[@.target="0.0.0.0"].nexthop' | tr -d "\n")
		[ -z "$peer" ] && peer=$(ip -4 r list dev "$iface" | grep via | grep -v default | grep -v metric | grep -v / | awk '{print $3; exit}' | tr -d "\n")
		[ -z "$peer" ] && peer=$(ip -4 r list dev "$iface" | grep kernel | awk '/proto kernel/ {print $1}' | grep -v / | tr -d "\n")
		[ -z "$peer" ] && peer=$(ip -4 r list dev "$iface" | awk '/^default via/ {print $3; exit}')
		[ -n "$addr" ] && [ -n "$peer" ] && {
			#logger -t "omr6in4" "addr: $addr - peer: $peer"
			if [ "$addr" != "$(uci -q get network.omr6in4.ipaddr)" ] || [ "$peer" != "$(uci -q get network.omr6in4.peeraddr)" ] || [ "$(ip -6 route show default dev 6in4-omr6in4 metric 1 | grep via)" = "" ] || [ "$(ip -6 route show default dev 6in4-omr6in4 table 61201 | grep via)" = "" ]; then
				logger -t "omr6in4" "Set network for OMR 6in4 to local $addr peer $peer"
				uci -q batch <<-EOF
					set network.omr6in4.ipaddr=$addr
					set network.omr6in4.peeraddr=$peer
					set network.omr6in4.metric=1
					commit network
				EOF
				if ip tunnel show | grep -q "^6in4-omr6in4:"; then
					ip tunnel change "6in4-omr6in4" mode sit local "${addr}" remote "${peer}" ttl 64 > /dev/null 2>&1
				else
					ifup omr6in4 > /dev/null 2>&1
				fi
				sleep 5
				#ipv6_addr=$(ip -6 addr show dev 6in4-omr6in4 | grep inet | awk '{print $2'} | cut -d/ -f1 | tr -d "\n")
				#ipv6_gw=$(echo $ipv6_addr | sed 's/1$/2')
				omr6in4_status=$(ubus call network.interface.omr6in4 status)
				ipv6_addr=$(echo "$omr6in4_status" | jsonfilter -q -l 1 -e '@["ipv6-address"][0].address' | tr -d "\n")
				ipv6_prefix=$(echo "$omr6in4_status" | jsonfilter -q -l 1 -e '@["ipv6-address"][0].mask' | tr -d "\n")
				[ -n "$ipv6_addr" ] && [ -n "$ipv6_prefix" ] && ip -6 addr add "$ipv6_addr/$ipv6_prefix" dev 6in4-omr6in4 > /dev/null 2>&1
				ipv6_gw=$(echo "$omr6in4_status" | jsonfilter -q -l 1 -e '@.route[@.target="::"].nexthop' | tr -d "\n")
				[ "$ipv6_gw" = "::" ] && ipv6_gw='fe80::a00:1'
				[ -z "$ipv6_gw" ] && ipv6_gw='fe80::a00:1'
				#[ -z "$ipv6_gw" ] && ipv6_gw='fe80::aff:ff01'
				[ -n "$ipv6_addr" ] && ip -6 route add "${ipv6_gw}" dev 6in4-omr6in4 > /dev/null 2>&1
				[ -n "$ipv6_addr" ] && ip -6 route add 2002::/16 dev 6in4-omr6in4 > /dev/null 2>&1
				[ -n "$ipv6_addr" ] && ip -6 route replace default via "${ipv6_gw}" dev 6in4-omr6in4 metric 1 > /dev/null 2>&1
				[ -n "$ipv6_addr" ] && ip -6 route replace default via "${ipv6_gw}" dev 6in4-omr6in4 table 61201 > /dev/null 2>&1
				[ -z "$(ip -6 rule show pref 0 table 61201 oif 6in4-omr6in4)" ] && ip -6 rule add oif 6in4-omr6in4 table 61201 pref 0 > /dev/null 2>&1
				# Resolve LAN device from firewall lan zone to support custom network section names.
				lan_dev=""
				lan_ip6assign=""
				lan_networks=$(uci -q get firewall.zone_lan.network)
				if [ -z "$lan_networks" ]; then
					for z in $(uci -q show firewall | sed -n "s/^firewall\.\([^=]*\)=zone$/\1/p"); do
						if [ "$(uci -q get firewall."$z".name)" = "lan" ]; then
							lan_networks=$(uci -q get firewall."$z".network)
							break
						fi
					done
				fi
				for netname in $lan_networks; do
					cand_dev=$(ubus call network.interface."$netname" status 2>/dev/null | jsonfilter -q -e '@.l3_device' | tr -d "\n")
					[ -z "$cand_dev" ] && cand_dev=$(uci -q get network."$netname".device)
					[ -z "$cand_dev" ] && cand_dev=$(uci -q get network."$netname".ifname)
					cand_dev=${cand_dev%% *}
					cand_ip6assign=$(uci -q get network."$netname".ip6assign)
					if [ -n "$cand_dev" ] && [ -d "${NET_CLASS_DIR}/$cand_dev" ]; then
						lan_dev="$cand_dev"
						[ -n "$cand_ip6assign" ] && lan_ip6assign="$cand_ip6assign"
						break
					fi
				done
				[ -z "$lan_dev" ] && lan_dev=$(uci -q get network.lan.device)
				[ -z "$lan_dev" ] && lan_dev=$(uci -q get network.lan.ifname)
				[ -z "$lan_dev" ] && lan_dev=$(uci -q get network.LAN.device)
				[ -z "$lan_dev" ] && lan_dev=$(uci -q get network.LAN.ifname)
				lan_dev=${lan_dev%% *}
				[ -z "$lan_dev" ] && lan_dev="br-lan"
				ula_prefix=$(uci -q get network.globals.ula_prefix)
				[ -z "$lan_ip6assign" ] && lan_ip6assign=$(uci -q get network.lan.ip6assign)
				[ -z "$lan_ip6assign" ] && lan_ip6assign=$(uci -q get network.LAN.ip6assign)
				[ -z "$lan_ip6assign" ] && lan_ip6assign="60"
				lan_ula_prefix=$(echo "$ula_prefix" | sed "s|/48|/$lan_ip6assign|")
				if [ -n "$lan_ula_prefix" ] && [ -d "${NET_CLASS_DIR}/$lan_dev" ]; then
					# Ensure a connected LAN ULA route exists and remove auto blackhole.
					ip -6 route replace "$lan_ula_prefix" dev "$lan_dev" > /dev/null 2>&1
					ip -6 route del unreachable "${ula_prefix%%/*}/48" > /dev/null 2>&1
				fi
				if [ "$(uci -q get openmptcprouter.settings.uci_route)" = "1" ]; then
					uci -q batch <<-EOF
						set network.omr6in4_route6_default=route6
						set network.omr6in4_route6_default.interface=omr6in4
						set network.omr6in4_route6_default.target='::'
						set network.omr6in4_route6_default.gateway="$ipv6_gw"
						commit network
					EOF
				fi
			fi
		}
	else
		ifdown omr6in4 > /dev/null 2>&1
	fi
	sleep 10
	[ -n "${OMR_6IN4_BREAK:-}" ] && break
done