#!/bin/sh

# Source function library
if [ -e /lib/lsb/init-functions ];then
	. /lib/lsb/init-functions
elif [ -e /etc/init.d/functions ];then
	. /etc/init.d/functions
fi

PATH=/sbin:/bin:/usr/sbin:/usr/bin
DESC=WireGuard

WG_DIR=/etc/wireguard
IFACE=wg0
PORT=51820

if [ -e /etc/default/static ];then
        source /etc/default/static
fi;

if [ -z "${IPV6ULA}" ];then
	IPV6ULA=$(echo $(cat /tmp/deviceid.txt)$(date -Ins) |sha1sum |cut -c31-40|awk '{printf "fd%s:%s:%s",substr($1,1,2),substr($1,3,4),substr($1,7,4)}')
fi;

if [ -e /etc/default/wireguard0 ];then
	source /etc/default/wireguard0
fi;

if [ -e /etc/default/vlans ];then
	source /etc/default/vlans
fi;

create_key() {
	if [ ! -e ${WG_DIR}/${1}.key ];then
		if [ -e ${WG_DIR}/${1}.pub ];then
			rm ${WG_DIR}/${1}.pub
		fi
		umask 0377
		/usr/bin/wg genkey >${WG_DIR}/${1}.key
	fi;
	if [ ! -e ${WG_DIR}/${1}.pub ];then
		umask 0133
		cat ${WG_DIR}/${1}.key |/usr/bin/wg pubkey > ${WG_DIR}/${1}.pub
	fi;
}

create_conf() {
	if [ ! -e ${WG_DIR}/${1}.key ] || [ ! -e ${WG_DIR}/${1}.pub ];then
		create_key ${1}
	fi;

	/usr/bin/wg set wg0 listen-port ${2} private-key ${WG_DIR}/${1}.key
	umask 0177
	/usr/bin/wg showconf ${1} > ${WG_DIR}/${1}.conf
}

create_psk() {
	if [ ! -e ${WG_DIR}/${1}.psk ];then
		umask 0377
		/usr/bin/wg genpsk > ${WG_DIR}/${1}.psk
	fi;
}

check_ip() {
	ORIG_IFS=${IFS}
	IFS=:;
	ep=(${1})
	IFS=${ORIG_IFS}

	if [ "${WG0_DNS}" == "${ep[0]}" ];then
		return 0;
	fi;

	EPIP=$(dig A +short ${WG0_DNS})
	if [ -n "${EPIP}" ] && [ "${ep[0]}" != "${EPIP}" ];then
		wg set wg0 peer ${WG0_PEER} endpoint ${EPIP}:${WG0_PORT}
	fi;

	if [ "${WG0_DHCP:-0}" == "1" ];then
		/usr/sbin/dhcpcd -n wg0
	fi;
}

check_peer() {
	if [ "${WG0_ENABLE:-0}" != "1" ];then
		return 0
	fi;

	if [ ! -e /run/dhcpcd-wg0.pid ] || ! kill -0  $(cat /run/dhcpcd-wg0.pid) 2>/dev/null;then
		while killall dhcpcd;do sleep 1;done
		PPP_IFACE=wg0 /etc/ppp/ipv6-up.d/10dhcpcd-pd;
	fi

	cur_time=$(date +%s)

	wg show wg0 dump |tail -n +2 |\
	while read peer preshare endpoint routes time trftx trfrx keepalive;do
		if [ "${peer}" != "${WG0_PEER}" ];then
			continue;
		fi;
		if [ $((${cur_time} - ${time})) -gt 120 ];then
			check_ip ${endpoint}
			break;
		elif [ "$(($(date +%M) % 5))" == "0" ];then
			/usr/sbin/dhcpcd -n wg0
		fi;
	done

}

if [ ! -d ${WG_DIR} ];then
	mkdir ${WG_DIR}
fi;

set -e

case $1 in
        start)
		echo "Starting ${DESC}"
		if [ ! -d /sys/class/net/${IFACE} ];then
			/sbin/ip link add ${IFACE} type wireguard
			if [ "${WG0_ENABLE}" = "1" ];then
				/sbin/ip link set dev ${IFACE} up
				/sbin/ip -6 addr flush  dev wg0 scope link
				/sbin/ip -6 addr add dev wg0  fe80::${IPV6ULA:2}/64
			fi;
		fi;

		if [ -n "${WG0_IP}" ];then
			for newip in ${WG0_IP};do
				ip addr add ${newip} dev wg0
			done;
		fi;

		if [ -n "${WG0_ROUTE}" ] && [ "${WG0_ENABLE}" = "1" ];then
			for newrt in ${WG0_ROUTE};do
				ip route add ${newrt} dev wg0
				ip route add ${newrt} dev wg0 table 100
				ip route add ${newrt} dev wg0 table 200
				for vlanid in ${VLANS};do
					ip route add ${newrt} dev wg0 table $((10000 + ${vlanid}))
				done
			done;
		fi;

		if [ ! -e ${WG_DIR}/${IFACE}.conf ];then
			if [ "${WG0_ENABLE}" != "1" ];then
				/sbin/ip link set dev ${IFACE} up
				create_conf ${IFACE} ${PORT}
				/sbin/ip link set dev ${IFACE} down
			else
				create_conf ${IFACE} ${PORT}
			fi;
		else
			/usr/bin/wg setconf ${IFACE} ${WG_DIR}/${IFACE}.conf
		fi;
		if [ "${WG0_ENABLE}" = "1" ];then
			if ! /usr/sbin/iptables -t nat -vnL WG >/dev/null 2>&1;then
				/usr/sbin/iptables -t nat -N WG
				/usr/sbin/iptables -t nat -I PREROUTING -j WG
			else
				/usr/sbin/iptables -t nat -F WG
			fi;

			if [ "${WG0_MASQ-0}" == "0" ];then
				for rt1 in ${WG0_ROUTE};do
					if [ "${rt1}" == "${rt1#*[0-9].[0-9]}" ];then
						continue
					fi;
					for rt2 in ${WG0_ROUTE};do
						if [ "${rt2}" != "${rt2#*[0-9].[0-9]}" ];then
							/usr/sbin/iptables -t nat -A WG -j ACCEPT -s  ${rt1} -d ${rt2} | :
						fi;
					done
				done
			fi;

			/usr/sbin/iptables -A FIREWALL -j ACCEPT -p udp --dport=$(wg show wg0 listen-port)
			/usr/sbin/iptables -t nat -A POSTROUTING -j MASQUERADE -o wg0
			if [ -n "${WG0_PEER}" ] && [ -n "${WG0_DNS}" ] && [ -n "${WG0_PORT}" ];then
				wg set wg0 peer ${WG0_PEER} endpoint ${WG0_DNS}:${WG0_PORT}
			fi;
			if [ "${WG0_DHCP:-0}" == "1" ];then
				PPP_IFACE=wg0 /etc/ppp/ipv6-up.d/10dhcpcd-pd
			elif [ -e /run/dhcpcd-wg0.pid ];then
				/usr/sbin/dhcpcd -k wg0
			fi;
		fi;
	;;
	stop)
		echo "Stoping ${DESC}"
		/usr/sbin/iptables -D FIREWALL -j ACCEPT -p udp --dport=$(wg show wg0 listen-port) >/dev/null 2>&1 ||:
		/usr/sbin/iptables -t nat -D POSTROUTING -j MASQUERADE -o wg0 >/dev/null 2>&1 ||:
		/usr/sbin/iptables -t nat -F WG
		if [ -d /sys/class/net/${IFACE} ];then
			umask 0377
			/usr/bin/wg showconf ${IFACE} > ${WG_DIR}/${IFACE}.conf
			/sbin/ip link set dev ${IFACE} down
			/sbin/ip link del ${IFACE}
		fi;
		if [ -d /sys/module/wireguard ];then
			rmmod wireguard
		fi;
	;;
	check)
		check_peer
	;;
esac

exit 0
