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

set -e

ME=$(basename "$0")

. /lib/overthebox

[ "$OTB_SERVICE_ID" ]

config="$(otb_device_get config | jq -r .)"
if [ -z "$config" ]; then
	otb_info "failed to get configuration"
	return
fi

_get() {
	otb_json_get "$config" "$1"
}

_setup_glorytun() {
	jq -r '@text "
	set glorytun.\(.dev)=mud
	set glorytun.\(.dev).enable=1
	set glorytun.\(.dev).dev=\(.dev)
	set glorytun.\(.dev).server=\(.server)
	set glorytun.\(.dev).port=\(.port)
	set glorytun.\(.dev).key=\(.key)
	set glorytun.\(.dev).mtu=\(.mtu)
	set glorytun.\(.dev).mtu_auto=\(.mtu_auto)

	delete network.\(.dev)
	set network.\(.dev)=interface
	set network.\(.dev).device=\(.dev)
	set network.\(.dev).proto=static
	set network.\(.dev).ipaddr=\(.ip_local)
	set network.\(.dev).netmask=255.255.255.0
	set network.\(.dev).gateway=\(.ip_peer)
	set network.\(.dev).metric=\(.metric)
	set network.\(.dev).ip4table=\(.table)
	set network.\(.dev).txqueuelen=1000
	set network.\(.dev).type=tunnel
	set network.\(.dev).multipath=off
	set network.\(.dev).ipv6=0
	set network.\(.dev).generatedby='"$ME"'

	del_list firewall.wan.network=\(.dev)
	delete firewall.tun.network
	add_list firewall.tun.network=\(.dev)
	"'
}

_setup_glorytun_dual_stack() {
	jq -r '@text "
	set glorytun.\(.dev)=mud
	set glorytun.\(.dev).enable=1
	set glorytun.\(.dev).dev=\(.dev)
	set glorytun.\(.dev).server=\(.server)
	set glorytun.\(.dev).port=\(.port)
	set glorytun.\(.dev).key=\(.key)
	set glorytun.\(.dev).mtu=\(.mtu)
	set glorytun.\(.dev).mtu_auto=\(.mtu_auto)

	delete network.\(.dev)
	set network.\(.dev)=interface
	set network.\(.dev).device=\(.dev)
	set network.\(.dev).proto=static
	set network.\(.dev).ipaddr=\(.ip_local)
	set network.\(.dev).netmask=255.255.255.0
	set network.\(.dev).gateway=\(.ip_peer)
	set network.\(.dev).metric=\(.metric)
	set network.\(.dev).ip4table=\(.table)
	set network.\(.dev).ip6addr=\(.ipv6_local)'"/112"'
	set network.\(.dev).ip6gw=\(.ipv6_peer)
	set network.\(.dev).ip6table=\(.table)
	set network.\(.dev).txqueuelen=1000
	set network.\(.dev).type=tunnel
	set network.\(.dev).multipath=off
	set network.\(.dev).ipv6=1
	set network.\(.dev).delegate=0
	set network.\(.dev).generatedby='"$ME"'

	del_list firewall.wan.network=\(.dev)
	delete firewall.tun.network
	add_list firewall.tun.network=\(.dev)
	"'
}

enable_lan_ipv6() {
	# Don't override current lan configuration
	ip=$(uci -q get network.lan.ipaddr)
	mask=$(uci -q get network.lan.netmask)

	jq -r '@text "
		delete network.lan
		set network.lan=interface
		set network.lan.device=br-lan
		set network.lan.proto=static
		set network.lan.ipaddr='"$ip"'
		set network.lan.netmask='"$mask"'
		set network.lan.multipath=off
		set network.lan.ip4table=lan
		set network.lan.ip6table=lan
		set network.lan.physicallayer=ethernet
		set network.lan.ip6addr=\(.ipv6_prefix)1/\(.ipv6_range)
		set network.lan.ip6assign=\(.ipv6_range)
		set network.lan.ipv6=1
		set network.lan.generatedby='"$ME"'

		set network.@device[0].ipv6=1

		set dhcp.lan.ra=server
		set dhcp.lan.dhcpv6=server

		set dhcp.@dnsmasq[0].filter_aaaa=0
	"'
}

disable_lan_ipv6() {
	# Don't override current lan configuration
	ip=$(uci -q get network.lan.ipaddr)
	mask=$(uci -q get network.lan.netmask)

	uci -q batch <<-EOF
		delete network.lan
		set network.lan=interface
		set network.lan.device=br-lan
		set network.lan.proto=static
		set network.lan.ipaddr=$ip
		set network.lan.netmask=$mask
		set network.lan.multipath=off
		set network.lan.ip4table=lan
		set network.lan.physicallayer=ethernet
		set network.lan.generatedby='"$ME"'

		set network.@device[0].ipv6=0

		set dhcp.lan.ra=disabled
		set dhcp.lan.dhcpv6=disabled

		set dhcp.dnsmasq[0].filter_aaaa=1
	EOF
}

_setup_shadowsocks() {
	jq -r '@text "
	set shadowsocks.proxy=client
	set shadowsocks.proxy.server=\(.server)
	set shadowsocks.proxy.port=\(.port)
	set shadowsocks.proxy.lport=\(.lport)
	set shadowsocks.proxy.method=\(.method)
	set shadowsocks.proxy.timeout=\(.timeout)
	set shadowsocks.proxy.reuse_port=\(.reuse_port)
	set shadowsocks.proxy.fast_open=\(.fast_open)
	set shadowsocks.proxy.disable_sni=\(.disable_sni)
	set shadowsocks.proxy.monitoring_ip=\(.monitoring_ip)
	set shadowsocks.proxy.track_interval=\(.track_interval)
	set shadowsocks.proxy.track_timeout=\(.track_timeout)
	set shadowsocks.proxy.track_retry=\(.track_retry)
	set shadowsocks.proxy.password=\(.password)
	set shadowsocks.proxy.disabled=\(.disabled)
	"'
}

_setup_log() {
	jq -r '@text "
	set system.@system[0].log_ip=\(.host)
	set system.@system[0].log_port=\(.port)
	set system.@system[0].log_proto=\(.protocol)
	set system.@system[0].log_prefix=\(.key)
	"'
}

_setup_graph() {
	jq -r '@text "
	set graph.opentsdb=opentsdb
	set graph.opentsdb.url=\(.host)
	set graph.opentsdb.freq=\(.write_frequency)

	set graph.provisioning=provisioning
	set graph.provisioning.freq=\(.write_frequency)
	"'
}

config_error=$(_get "error // empty")

if [ "$config_error" ]; then
	echo "$config_error" >&2
	exit 1
fi

# Delete last conf
for conf in glorytun shadowsocks graph otb-graph; do
	true > /etc/config/"$conf"
	uci -q revert "$conf"
done

uci -q show | sed -n "s/.generatedby='$ME'//p" | xargs -r -n 1 uci -q delete

# Get current IPv6 status
lanV6="$(uci -q get network.lan.ipv6)" || echo "0"
brlanV6="$(uci -q get network.@device[0].ipv6)" || echo "0"

# Activate IPv6 on glorytun depending on configuration
glorytun_mud_conf=$(_get "glorytun_mud_conf")
ipv6_peer=$(echo "$glorytun_mud_conf" | jq '.ipv6_peer')
ipv6_local=$(echo "$glorytun_mud_conf" | jq '.ipv6_local')
if [ "$ipv6_peer" != "null" ] && [ "$ipv6_local"  != "null" ] ; then
	echo "$glorytun_mud_conf" | _setup_glorytun_dual_stack | uci -q batch

	if  [ "$lanV6" != 1 ] || [ "$brlanV6" != 1 ]; then
		_get ipv6_conf.lan_conf | enable_lan_ipv6 | uci -q batch
	fi
else
	echo "$glorytun_mud_conf" | _setup_glorytun | uci -q batch

	if  [ "$lanV6" = 1 ] || [ "$brlanV6" = 1 ]; then
		disable_lan_ipv6
	fi
fi

_get shadow_conf | _setup_shadowsocks | uci -q batch
_get log_conf | _setup_log | uci -q batch
_get graph_conf | _setup_graph | uci -q batch
uci -q commit
